LCOV - code coverage report
Current view: top level - gcc/fortran - openmp.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 93.0 % 7444 6924
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 220 220
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              :   {"cancel", GFC_OMP_DIR_EXECUTABLE, ST_OMP_CANCEL},
      71              :   {"critical", GFC_OMP_DIR_EXECUTABLE, ST_OMP_CRITICAL},
      72              :   /* {"declare induction", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_INDUCTION}, */
      73              :   /* {"declare mapper", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_MAPPER}, */
      74              :   {"declare reduction", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_REDUCTION},
      75              :   {"declare simd", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_SIMD},
      76              :   {"declare target", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_TARGET},
      77              :   {"declare variant", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_VARIANT},
      78              :   {"depobj", GFC_OMP_DIR_EXECUTABLE, ST_OMP_DEPOBJ},
      79              :   {"dispatch", GFC_OMP_DIR_EXECUTABLE, ST_OMP_DISPATCH},
      80              :   {"distribute", GFC_OMP_DIR_EXECUTABLE, ST_OMP_DISTRIBUTE},
      81              :   {"do", GFC_OMP_DIR_EXECUTABLE, ST_OMP_DO},
      82              :   /* "error" becomes GFC_OMP_DIR_EXECUTABLE with at(execution) */
      83              :   {"error", GFC_OMP_DIR_UTILITY, ST_OMP_ERROR},
      84              :   /* {"flatten", GFC_OMP_DIR_EXECUTABLE, ST_OMP_FLATTEN}, */
      85              :   {"flush", GFC_OMP_DIR_EXECUTABLE, ST_OMP_FLUSH},
      86              :   /* {"fuse", GFC_OMP_DIR_EXECUTABLE, ST_OMP_FLUSE}, */
      87              :   {"groupprivate", GFC_OMP_DIR_DECLARATIVE, ST_OMP_GROUPPRIVATE},
      88              :   /* {"interchange", GFC_OMP_DIR_EXECUTABLE, ST_OMP_INTERCHANGE}, */
      89              :   {"interop", GFC_OMP_DIR_EXECUTABLE, ST_OMP_INTEROP},
      90              :   {"loop", GFC_OMP_DIR_EXECUTABLE, ST_OMP_LOOP},
      91              :   {"masked", GFC_OMP_DIR_EXECUTABLE, ST_OMP_MASKED},
      92              :   {"metadirective", GFC_OMP_DIR_META, ST_OMP_METADIRECTIVE},
      93              :   /* Note: gfc_match_omp_nothing returns ST_NONE.  */
      94              :   {"nothing", GFC_OMP_DIR_UTILITY, ST_OMP_NOTHING},
      95              :   /* Special case; for now map to the first one.
      96              :      ordered-blockassoc = ST_OMP_ORDERED
      97              :      ordered-standalone = ST_OMP_ORDERED_DEPEND + depend/doacross.  */
      98              :   {"ordered", GFC_OMP_DIR_EXECUTABLE, ST_OMP_ORDERED},
      99              :   {"parallel", GFC_OMP_DIR_EXECUTABLE, ST_OMP_PARALLEL},
     100              :   {"requires", GFC_OMP_DIR_INFORMATIONAL, ST_OMP_REQUIRES},
     101              :   {"scan", GFC_OMP_DIR_SUBSIDIARY, ST_OMP_SCAN},
     102              :   {"scope", GFC_OMP_DIR_EXECUTABLE, ST_OMP_SCOPE},
     103              :   {"sections", GFC_OMP_DIR_EXECUTABLE, ST_OMP_SECTIONS},
     104              :   {"section", GFC_OMP_DIR_SUBSIDIARY, ST_OMP_SECTION},
     105              :   {"simd", GFC_OMP_DIR_EXECUTABLE, ST_OMP_SIMD},
     106              :   {"single", GFC_OMP_DIR_EXECUTABLE, ST_OMP_SINGLE},
     107              :   /* {"split", GFC_OMP_DIR_EXECUTABLE, ST_OMP_SPLIT}, */
     108              :   /* {"strip", GFC_OMP_DIR_EXECUTABLE, ST_OMP_STRIP}, */
     109              :   {"target data", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET_DATA},
     110              :   {"target enter data", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET_ENTER_DATA},
     111              :   {"target exit data", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET_EXIT_DATA},
     112              :   {"target update", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET_UPDATE},
     113              :   {"target", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET},
     114              :   /* {"taskgraph", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TASKGRAPH}, */
     115              :   /* {"task iteration", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TASK_ITERATION}, */
     116              :   {"taskloop", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TASKLOOP},
     117              :   {"taskwait", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TASKWAIT},
     118              :   {"taskyield", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TASKYIELD},
     119              :   {"task", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TASK},
     120              :   {"teams", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TEAMS},
     121              :   {"threadprivate", GFC_OMP_DIR_DECLARATIVE, ST_OMP_THREADPRIVATE},
     122              :   {"tile", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TILE},
     123              :   {"unroll", GFC_OMP_DIR_EXECUTABLE, ST_OMP_UNROLL},
     124              :   /* {"workdistribute", GFC_OMP_DIR_EXECUTABLE, ST_OMP_WORKDISTRIBUTE}, */
     125              :   {"workshare", GFC_OMP_DIR_EXECUTABLE, ST_OMP_WORKSHARE},
     126              : };
     127              : 
     128              : 
     129              : /* Match an end of OpenMP directive.  End of OpenMP directive is optional
     130              :    whitespace, followed by '\n' or comment '!'.  In the special case where a
     131              :    context selector is being matched, match against ')' instead.  */
     132              : 
     133              : static match
     134        54739 : gfc_match_omp_eos (void)
     135              : {
     136        54739 :   locus old_loc;
     137        54739 :   char c;
     138              : 
     139        54739 :   old_loc = gfc_current_locus;
     140        54739 :   gfc_gobble_whitespace ();
     141              : 
     142        54739 :   if (gfc_matching_omp_context_selector)
     143              :     {
     144          269 :       if (gfc_peek_ascii_char () == ')')
     145              :         return MATCH_YES;
     146              :     }
     147              :   else
     148              :     {
     149        54470 :       c = gfc_next_ascii_char ();
     150        54470 :       switch (c)
     151              :         {
     152            0 :         case '!':
     153            0 :           do
     154            0 :             c = gfc_next_ascii_char ();
     155            0 :           while (c != '\n');
     156              :           /* Fall through */
     157              : 
     158        52765 :         case '\n':
     159        52765 :           return MATCH_YES;
     160              :         }
     161              :     }
     162              : 
     163         1706 :   gfc_current_locus = old_loc;
     164         1706 :   return MATCH_NO;
     165              : }
     166              : 
     167              : match
     168        13141 : gfc_match_omp_eos_error (void)
     169              : {
     170        13141 :   if (gfc_match_omp_eos() == MATCH_YES)
     171              :     return MATCH_YES;
     172              : 
     173           35 :   gfc_error ("Unexpected junk at %C");
     174           35 :   return MATCH_ERROR;
     175              : }
     176              : 
     177              : 
     178              : /* Free an omp_clauses structure.  */
     179              : 
     180              : void
     181        60856 : gfc_free_omp_clauses (gfc_omp_clauses *c)
     182              : {
     183        60856 :   int i;
     184        60856 :   if (c == NULL)
     185              :     return;
     186              : 
     187        34244 :   gfc_free_expr (c->if_expr);
     188       410928 :   for (i = 0; i < OMP_IF_LAST; i++)
     189       342440 :     gfc_free_expr (c->if_exprs[i]);
     190        34244 :   gfc_free_expr (c->self_expr);
     191        34244 :   gfc_free_expr (c->final_expr);
     192        34244 :   gfc_free_expr (c->num_threads);
     193        34244 :   gfc_free_expr (c->chunk_size);
     194        34244 :   gfc_free_expr (c->safelen_expr);
     195        34244 :   gfc_free_expr (c->simdlen_expr);
     196        34244 :   gfc_free_expr (c->num_teams_lower);
     197        34244 :   gfc_free_expr (c->num_teams_upper);
     198        34244 :   gfc_free_expr (c->device);
     199        34244 :   gfc_free_expr (c->dyn_groupprivate);
     200        34244 :   gfc_free_expr (c->thread_limit);
     201        34244 :   gfc_free_expr (c->dist_chunk_size);
     202        34244 :   gfc_free_expr (c->grainsize);
     203        34244 :   gfc_free_expr (c->hint);
     204        34244 :   gfc_free_expr (c->num_tasks);
     205        34244 :   gfc_free_expr (c->priority);
     206        34244 :   gfc_free_expr (c->detach);
     207        34244 :   gfc_free_expr (c->novariants);
     208        34244 :   gfc_free_expr (c->nocontext);
     209        34244 :   gfc_free_expr (c->async_expr);
     210        34244 :   gfc_free_expr (c->gang_num_expr);
     211        34244 :   gfc_free_expr (c->gang_static_expr);
     212        34244 :   gfc_free_expr (c->worker_expr);
     213        34244 :   gfc_free_expr (c->vector_expr);
     214        34244 :   gfc_free_expr (c->num_gangs_expr);
     215        34244 :   gfc_free_expr (c->num_workers_expr);
     216        34244 :   gfc_free_expr (c->vector_length_expr);
     217      1404004 :   for (i = 0; i < OMP_LIST_NUM; i++)
     218      1335516 :     gfc_free_omp_namelist (c->lists[i],
     219      1335516 :                            i == OMP_LIST_AFFINITY || i == OMP_LIST_DEPEND,
     220              :                            i == OMP_LIST_ALLOCATE,
     221              :                            i == OMP_LIST_USES_ALLOCATORS,
     222              :                            i == OMP_LIST_INIT);
     223        34244 :   gfc_free_expr_list (c->wait_list);
     224        34244 :   gfc_free_expr_list (c->tile_list);
     225        34244 :   gfc_free_expr_list (c->sizes_list);
     226        34244 :   free (const_cast<char *> (c->critical_name));
     227        34244 :   if (c->assume)
     228              :     {
     229           23 :       free (c->assume->absent);
     230           23 :       free (c->assume->contains);
     231           23 :       gfc_free_expr_list (c->assume->holds);
     232           23 :       free (c->assume);
     233              :     }
     234        34244 :   free (c);
     235              : }
     236              : 
     237              : /* Free oacc_declare structures.  */
     238              : 
     239              : void
     240           76 : gfc_free_oacc_declare_clauses (struct gfc_oacc_declare *oc)
     241              : {
     242           76 :   struct gfc_oacc_declare *decl = oc;
     243              : 
     244           76 :   do
     245              :     {
     246           76 :       struct gfc_oacc_declare *next;
     247              : 
     248           76 :       next = decl->next;
     249           76 :       gfc_free_omp_clauses (decl->clauses);
     250           76 :       free (decl);
     251           76 :       decl = next;
     252              :     }
     253           76 :   while (decl);
     254           76 : }
     255              : 
     256              : /* Free expression list. */
     257              : void
     258       103678 : gfc_free_expr_list (gfc_expr_list *list)
     259              : {
     260       103678 :   gfc_expr_list *n;
     261              : 
     262       105081 :   for (; list; list = n)
     263              :     {
     264         1403 :       n = list->next;
     265         1403 :       free (list);
     266              :     }
     267       103678 : }
     268              : 
     269              : /* Free an !$omp declare simd construct list.  */
     270              : 
     271              : void
     272          236 : gfc_free_omp_declare_simd (gfc_omp_declare_simd *ods)
     273              : {
     274          236 :   if (ods)
     275              :     {
     276          236 :       gfc_free_omp_clauses (ods->clauses);
     277          236 :       free (ods);
     278              :     }
     279          236 : }
     280              : 
     281              : void
     282       515764 : gfc_free_omp_declare_simd_list (gfc_omp_declare_simd *list)
     283              : {
     284       516000 :   while (list)
     285              :     {
     286          236 :       gfc_omp_declare_simd *current = list;
     287          236 :       list = list->next;
     288          236 :       gfc_free_omp_declare_simd (current);
     289              :     }
     290       515764 : }
     291              : 
     292              : static void
     293          727 : gfc_free_omp_trait_property_list (gfc_omp_trait_property *list)
     294              : {
     295         1134 :   while (list)
     296              :     {
     297          407 :       gfc_omp_trait_property *current = list;
     298          407 :       list = list->next;
     299          407 :       switch (current->property_kind)
     300              :         {
     301           24 :         case OMP_TRAIT_PROPERTY_ID:
     302           24 :           free (current->name);
     303           24 :           break;
     304          261 :         case OMP_TRAIT_PROPERTY_NAME_LIST:
     305          261 :           if (current->is_name)
     306          168 :             free (current->name);
     307              :           break;
     308           15 :         case OMP_TRAIT_PROPERTY_CLAUSE_LIST:
     309           15 :           gfc_free_omp_clauses (current->clauses);
     310           15 :           break;
     311              :         default:
     312              :           break;
     313              :         }
     314          407 :       free (current);
     315              :     }
     316          727 : }
     317              : 
     318              : static void
     319          599 : gfc_free_omp_selector_list (gfc_omp_selector *list)
     320              : {
     321         1326 :   while (list)
     322              :     {
     323          727 :       gfc_omp_selector *current = list;
     324          727 :       list = list->next;
     325          727 :       gfc_free_omp_trait_property_list (current->properties);
     326          727 :       free (current);
     327              :     }
     328          599 : }
     329              : 
     330              : static void
     331          667 : gfc_free_omp_set_selector_list (gfc_omp_set_selector *list)
     332              : {
     333         1266 :   while (list)
     334              :     {
     335          599 :       gfc_omp_set_selector *current = list;
     336          599 :       list = list->next;
     337          599 :       gfc_free_omp_selector_list (current->trait_selectors);
     338          599 :       free (current);
     339              :     }
     340          667 : }
     341              : 
     342              : /* Free an !$omp declare variant construct list.  */
     343              : 
     344              : void
     345       515764 : gfc_free_omp_declare_variant_list (gfc_omp_declare_variant *list)
     346              : {
     347       516217 :   while (list)
     348              :     {
     349          453 :       gfc_omp_declare_variant *current = list;
     350          453 :       list = list->next;
     351          453 :       gfc_free_omp_set_selector_list (current->set_selectors);
     352          453 :       gfc_free_omp_namelist (current->adjust_args_list, false, false, false,
     353              :                              false);
     354          453 :       free (current);
     355              :     }
     356       515764 : }
     357              : 
     358              : /* Free an !$omp declare reduction.  */
     359              : 
     360              : void
     361         1118 : gfc_free_omp_udr (gfc_omp_udr *omp_udr)
     362              : {
     363         1118 :   if (omp_udr)
     364              :     {
     365          607 :       gfc_free_omp_udr (omp_udr->next);
     366          607 :       gfc_free_namespace (omp_udr->combiner_ns);
     367          607 :       if (omp_udr->initializer_ns)
     368          377 :         gfc_free_namespace (omp_udr->initializer_ns);
     369          607 :       free (omp_udr);
     370              :     }
     371         1118 : }
     372              : 
     373              : /* Free variants of an !$omp metadirective construct.  */
     374              : 
     375              : void
     376           93 : gfc_free_omp_variants (gfc_omp_variant *variant)
     377              : {
     378          284 :   while (variant)
     379              :     {
     380          191 :       gfc_omp_variant *next_variant = variant->next;
     381          191 :       gfc_free_omp_set_selector_list (variant->selectors);
     382          191 :       free (variant);
     383          191 :       variant = next_variant;
     384              :     }
     385           93 : }
     386              : 
     387              : static gfc_omp_udr *
     388         4709 : gfc_find_omp_udr (gfc_namespace *ns, const char *name, gfc_typespec *ts)
     389              : {
     390         4709 :   gfc_symtree *st;
     391              : 
     392         4709 :   if (ns == NULL)
     393          467 :     ns = gfc_current_ns;
     394         5657 :   do
     395              :     {
     396         5657 :       gfc_omp_udr *omp_udr;
     397              : 
     398         5657 :       st = gfc_find_symtree (ns->omp_udr_root, name);
     399         5657 :       if (st != NULL)
     400              :         {
     401          934 :           for (omp_udr = st->n.omp_udr; omp_udr; omp_udr = omp_udr->next)
     402          934 :             if (ts == NULL)
     403              :               return omp_udr;
     404          567 :             else if (gfc_compare_types (&omp_udr->ts, ts))
     405              :               {
     406          479 :                 if (ts->type == BT_CHARACTER)
     407              :                   {
     408           60 :                     if (omp_udr->ts.u.cl->length == NULL)
     409              :                       return omp_udr;
     410           36 :                     if (ts->u.cl->length == NULL)
     411            0 :                       continue;
     412           36 :                     if (gfc_compare_expr (omp_udr->ts.u.cl->length,
     413              :                                           ts->u.cl->length,
     414              :                                           INTRINSIC_EQ) != 0)
     415           12 :                       continue;
     416              :                   }
     417          443 :                 return omp_udr;
     418              :               }
     419              :         }
     420              : 
     421              :       /* Don't escape an interface block.  */
     422         4823 :       if (ns && !ns->has_import_set
     423         4823 :           && ns->proc_name && ns->proc_name->attr.if_source == IFSRC_IFBODY)
     424              :         break;
     425              : 
     426         4823 :       ns = ns->parent;
     427              :     }
     428         4823 :   while (ns != NULL);
     429              : 
     430              :   return NULL;
     431              : }
     432              : 
     433              : 
     434              : /* Match a variable/common block list and construct a namelist from it;
     435              :    if has_all_memory != NULL, *has_all_memory is set and omp_all_memory
     436              :    yields a list->sym NULL entry. */
     437              : 
     438              : static match
     439        30914 : gfc_match_omp_variable_list (const char *str, gfc_omp_namelist **list,
     440              :                              bool allow_common, bool *end_colon = NULL,
     441              :                              gfc_omp_namelist ***headp = NULL,
     442              :                              bool allow_sections = false,
     443              :                              bool allow_derived = false,
     444              :                              bool *has_all_memory = NULL,
     445              :                              bool reject_common_vars = false,
     446              :                              bool reverse_order = false)
     447              : {
     448        30914 :   gfc_omp_namelist *head, *tail, *p;
     449        30914 :   locus old_loc, cur_loc;
     450        30914 :   char n[GFC_MAX_SYMBOL_LEN+1];
     451        30914 :   gfc_symbol *sym;
     452        30914 :   match m;
     453        30914 :   gfc_symtree *st;
     454              : 
     455        30914 :   head = tail = NULL;
     456              : 
     457        30914 :   old_loc = gfc_current_locus;
     458        30914 :   if (has_all_memory)
     459          705 :     *has_all_memory = false;
     460        30914 :   m = gfc_match (str);
     461        30914 :   if (m != MATCH_YES)
     462              :     return m;
     463              : 
     464        37567 :   for (;;)
     465              :     {
     466        37567 :       gfc_gobble_whitespace ();
     467        37567 :       cur_loc = gfc_current_locus;
     468              : 
     469        37567 :       m = gfc_match_name (n);
     470        37567 :       if (m == MATCH_YES && strcmp (n, "omp_all_memory") == 0)
     471              :         {
     472           23 :           locus loc = gfc_get_location_range (NULL, 0, &cur_loc, 1,
     473              :                                               &gfc_current_locus);
     474           23 :           if (!has_all_memory)
     475              :             {
     476            2 :               gfc_error ("%<omp_all_memory%> at %L not permitted in this "
     477              :                          "clause", &loc);
     478            2 :               goto cleanup;
     479              :             }
     480           21 :           *has_all_memory = true;
     481           21 :           p = gfc_get_omp_namelist ();
     482           21 :           if (head == NULL)
     483              :             head = tail = p;
     484              :           else
     485              :             {
     486            3 :               tail->next = p;
     487            3 :               tail = tail->next;
     488              :             }
     489           21 :           tail->where = loc;
     490           21 :           goto next_item;
     491              :         }
     492        37290 :       if (m == MATCH_YES)
     493              :         {
     494        37290 :           gfc_symtree *st;
     495        37290 :           if ((m = gfc_get_ha_sym_tree (n, &st) ? MATCH_ERROR : MATCH_YES)
     496              :               == MATCH_YES)
     497        37290 :             sym = st->n.sym;
     498              :         }
     499        37544 :       switch (m)
     500              :         {
     501        37290 :         case MATCH_YES:
     502        37290 :           gfc_expr *expr;
     503        37290 :           expr = NULL;
     504        37290 :           gfc_gobble_whitespace ();
     505        22747 :           if ((allow_sections && gfc_peek_ascii_char () == '(')
     506        55948 :               || (allow_derived && gfc_peek_ascii_char () == '%'))
     507              :             {
     508         6316 :               gfc_current_locus = cur_loc;
     509         6316 :               m = gfc_match_variable (&expr, 0);
     510         6316 :               switch (m)
     511              :                 {
     512            4 :                 case MATCH_ERROR:
     513           12 :                   goto cleanup;
     514            0 :                 case MATCH_NO:
     515            0 :                   goto syntax;
     516         6312 :                 default:
     517         6312 :                   break;
     518              :                 }
     519         6312 :               if (gfc_is_coindexed (expr))
     520              :                 {
     521            5 :                   gfc_error ("List item shall not be coindexed at %L",
     522            5 :                              &expr->where);
     523            5 :                   goto cleanup;
     524              :                 }
     525              :             }
     526        37281 :           gfc_set_sym_referenced (sym);
     527        37281 :           p = gfc_get_omp_namelist ();
     528        37281 :           if (head == NULL)
     529              :             head = tail = p;
     530        10059 :           else if (reverse_order)
     531              :             {
     532           57 :               p->next = head;
     533           57 :               head = p;
     534              :             }
     535              :           else
     536              :             {
     537        10002 :               tail->next = p;
     538        10002 :               tail = tail->next;
     539              :             }
     540        37281 :           p->sym = sym;
     541        37281 :           p->expr = expr;
     542        37281 :           p->where = gfc_get_location_range (NULL, 0, &cur_loc, 1,
     543              :                                              &gfc_current_locus);
     544        37281 :           if (reject_common_vars && sym->attr.in_common)
     545              :             {
     546            3 :               gcc_assert (allow_common);
     547            3 :               gfc_error ("%qs at %L is part of the common block %</%s/%> and "
     548              :                          "may only be specificed implicitly via the named "
     549              :                          "common block", sym->name, &cur_loc,
     550            3 :                          sym->common_head->name);
     551            3 :               goto cleanup;
     552              :             }
     553        37278 :           goto next_item;
     554          254 :         case MATCH_NO:
     555          254 :           break;
     556            0 :         case MATCH_ERROR:
     557            0 :           goto cleanup;
     558              :         }
     559              : 
     560          254 :       if (!allow_common)
     561           10 :         goto syntax;
     562              : 
     563          244 :       m = gfc_match ("/ %n /", n);
     564          244 :       if (m == MATCH_ERROR)
     565            0 :         goto cleanup;
     566          244 :       if (m == MATCH_NO)
     567           19 :         goto syntax;
     568              : 
     569          225 :       cur_loc = gfc_get_location_range (NULL, 0, &cur_loc, 1,
     570              :                                         &gfc_current_locus);
     571          225 :       st = gfc_find_symtree (gfc_current_ns->common_root, n);
     572          225 :       if (st == NULL)
     573              :         {
     574            2 :           gfc_error ("COMMON block %</%s/%> not found at %L", n, &cur_loc);
     575            2 :           goto cleanup;
     576              :         }
     577          724 :       for (sym = st->n.common->head; sym; sym = sym->common_next)
     578              :         {
     579          501 :           gfc_set_sym_referenced (sym);
     580          501 :           p = gfc_get_omp_namelist ();
     581          501 :           if (head == NULL)
     582              :             head = tail = p;
     583          325 :           else if (reverse_order)
     584              :             {
     585            0 :               p->next = head;
     586            0 :               head = p;
     587              :             }
     588              :           else
     589              :             {
     590          325 :               tail->next = p;
     591          325 :               tail = tail->next;
     592              :             }
     593          501 :           p->sym = sym;
     594          501 :           p->where = cur_loc;
     595              :         }
     596              : 
     597          223 :     next_item:
     598        37522 :       if (end_colon && gfc_match_char (':') == MATCH_YES)
     599              :         {
     600          793 :           *end_colon = true;
     601          793 :           break;
     602              :         }
     603        36729 :       if (gfc_match_char (')') == MATCH_YES)
     604              :         break;
     605        10128 :       if (gfc_match_char (',') != MATCH_YES)
     606           19 :         goto syntax;
     607              :     }
     608              : 
     609        36908 :   while (*list)
     610         9514 :     list = &(*list)->next;
     611              : 
     612        27394 :   *list = head;
     613        27394 :   if (headp)
     614        21564 :     *headp = list;
     615              :   return MATCH_YES;
     616              : 
     617           48 : syntax:
     618           48 :   gfc_error ("Syntax error in OpenMP variable list at %C");
     619              : 
     620           64 : cleanup:
     621           64 :   gfc_free_omp_namelist (head, false, false, false, false);
     622           64 :   gfc_current_locus = old_loc;
     623           64 :   return MATCH_ERROR;
     624              : }
     625              : 
     626              : /* Match a variable/procedure/common block list and construct a namelist
     627              :    from it.  */
     628              : 
     629              : static match
     630          360 : gfc_match_omp_to_link (const char *str, gfc_omp_namelist **list)
     631              : {
     632          360 :   gfc_omp_namelist *head, *tail, *p;
     633          360 :   locus old_loc, cur_loc;
     634          360 :   char n[GFC_MAX_SYMBOL_LEN+1];
     635          360 :   gfc_symbol *sym;
     636          360 :   match m;
     637          360 :   gfc_symtree *st;
     638              : 
     639          360 :   head = tail = NULL;
     640              : 
     641          360 :   old_loc = gfc_current_locus;
     642              : 
     643          360 :   m = gfc_match (str);
     644          360 :   if (m != MATCH_YES)
     645              :     return m;
     646              : 
     647          544 :   for (;;)
     648              :     {
     649          544 :       cur_loc = gfc_current_locus;
     650          544 :       m = gfc_match_symbol (&sym, 1);
     651          544 :       switch (m)
     652              :         {
     653          503 :         case MATCH_YES:
     654          503 :           p = gfc_get_omp_namelist ();
     655          503 :           if (head == NULL)
     656              :             head = tail = p;
     657              :           else
     658              :             {
     659          192 :               tail->next = p;
     660          192 :               tail = tail->next;
     661              :             }
     662          503 :           tail->sym = sym;
     663          503 :           tail->where = cur_loc;
     664          503 :           goto next_item;
     665              :         case MATCH_NO:
     666              :           break;
     667            0 :         case MATCH_ERROR:
     668            0 :           goto cleanup;
     669              :         }
     670              : 
     671           41 :       m = gfc_match (" / %n /", n);
     672           41 :       if (m == MATCH_ERROR)
     673            0 :         goto cleanup;
     674           41 :       if (m == MATCH_NO)
     675            0 :         goto syntax;
     676              : 
     677           41 :       st = gfc_find_symtree (gfc_current_ns->common_root, n);
     678           41 :       if (st == NULL)
     679              :         {
     680            0 :           gfc_error ("COMMON block /%s/ not found at %C", n);
     681            0 :           goto cleanup;
     682              :         }
     683           41 :       p = gfc_get_omp_namelist ();
     684           41 :       if (head == NULL)
     685              :         head = tail = p;
     686              :       else
     687              :         {
     688            4 :           tail->next = p;
     689            4 :           tail = tail->next;
     690              :         }
     691           41 :       tail->u.common = st->n.common;
     692           41 :       tail->where = cur_loc;
     693              : 
     694          544 :     next_item:
     695          544 :       if (gfc_match_char (')') == MATCH_YES)
     696              :         break;
     697          196 :       if (gfc_match_char (',') != MATCH_YES)
     698            0 :         goto syntax;
     699              :     }
     700              : 
     701          359 :   while (*list)
     702           11 :     list = &(*list)->next;
     703              : 
     704          348 :   *list = head;
     705          348 :   return MATCH_YES;
     706              : 
     707            0 : syntax:
     708            0 :   gfc_error ("Syntax error in OpenMP variable list at %C");
     709              : 
     710            0 : cleanup:
     711            0 :   gfc_free_omp_namelist (head, false, false, false, false);
     712            0 :   gfc_current_locus = old_loc;
     713            0 :   return MATCH_ERROR;
     714              : }
     715              : 
     716              : /* Match detach(event-handle).  */
     717              : 
     718              : static match
     719          126 : gfc_match_omp_detach (gfc_expr **expr)
     720              : {
     721          126 :   locus old_loc = gfc_current_locus;
     722              : 
     723          126 :   if (gfc_match ("detach ( ") != MATCH_YES)
     724            0 :     goto syntax_error;
     725              : 
     726          126 :   if (gfc_match_variable (expr, 0) != MATCH_YES)
     727            0 :     goto syntax_error;
     728              : 
     729          126 :   if (gfc_match_char (')') != MATCH_YES)
     730            0 :     goto syntax_error;
     731              : 
     732              :   return MATCH_YES;
     733              : 
     734            0 : syntax_error:
     735            0 :    gfc_error ("Syntax error in OpenMP detach clause at %C");
     736            0 :    gfc_current_locus = old_loc;
     737            0 :    return MATCH_ERROR;
     738              : 
     739              : }
     740              : 
     741              : /* Match doacross(sink : ...) construct a namelist from it;
     742              :    if depend is true, match legacy 'depend(sink : ...)'.  */
     743              : 
     744              : static match
     745          241 : gfc_match_omp_doacross_sink (gfc_omp_namelist **list, bool depend)
     746              : {
     747          241 :   char n[GFC_MAX_SYMBOL_LEN+1];
     748          241 :   gfc_omp_namelist *head, *tail, *p;
     749          241 :   locus old_loc, cur_loc;
     750          241 :   gfc_symbol *sym;
     751              : 
     752          241 :   head = tail = NULL;
     753              : 
     754          241 :   old_loc = gfc_current_locus;
     755              : 
     756         2231 :   for (;;)
     757              :     {
     758         1236 :       gfc_gobble_whitespace ();
     759         1236 :       cur_loc = gfc_current_locus;
     760              : 
     761         1236 :       if (gfc_match_name (n) != MATCH_YES)
     762            1 :         goto syntax;
     763         1235 :       locus loc = gfc_get_location_range (NULL, 0, &cur_loc, 1,
     764              :                                           &gfc_current_locus);
     765         1235 :       if (UNLIKELY (strcmp (n, "omp_all_memory") == 0))
     766              :         {
     767            1 :           gfc_error ("%<omp_all_memory%> used with dependence-type "
     768              :                      "other than OUT or INOUT at %L", &loc);
     769            1 :           goto cleanup;
     770              :         }
     771         1234 :       sym = NULL;
     772         1234 :       if (!(strcmp (n, "omp_cur_iteration") == 0))
     773              :         {
     774         1229 :           gfc_symtree *st;
     775         1229 :           if (gfc_get_ha_sym_tree (n, &st))
     776            0 :             goto syntax;
     777         1229 :           sym = st->n.sym;
     778         1229 :           gfc_set_sym_referenced (sym);
     779              :         }
     780         1234 :       p = gfc_get_omp_namelist ();
     781         1234 :       if (head == NULL)
     782              :         {
     783          239 :           head = tail = p;
     784          253 :           head->u.depend_doacross_op = (depend ? OMP_DEPEND_SINK_FIRST
     785              :                                                : OMP_DOACROSS_SINK_FIRST);
     786              :         }
     787              :       else
     788              :         {
     789          995 :           tail->next = p;
     790          995 :           tail = tail->next;
     791          995 :           tail->u.depend_doacross_op = OMP_DOACROSS_SINK;
     792              :         }
     793         1234 :       tail->sym = sym;
     794         1234 :       tail->expr = NULL;
     795         1234 :       tail->where = loc;
     796         1234 :       if (gfc_match_char ('+') == MATCH_YES)
     797              :         {
     798          154 :           if (gfc_match_literal_constant (&tail->expr, 0) != MATCH_YES)
     799            0 :             goto syntax;
     800              :         }
     801         1080 :       else if (gfc_match_char ('-') == MATCH_YES)
     802              :         {
     803          418 :           if (gfc_match_literal_constant (&tail->expr, 0) != MATCH_YES)
     804            1 :             goto syntax;
     805          417 :           tail->expr = gfc_uminus (tail->expr);
     806              :         }
     807         1233 :       if (gfc_match_char (')') == MATCH_YES)
     808              :         break;
     809          995 :       if (gfc_match_char (',') != MATCH_YES)
     810            0 :         goto syntax;
     811          995 :     }
     812              : 
     813         1030 :   while (*list)
     814          792 :     list = &(*list)->next;
     815              : 
     816          238 :   *list = head;
     817          238 :   return MATCH_YES;
     818              : 
     819            2 : syntax:
     820            2 :   gfc_error ("Syntax error in OpenMP SINK dependence-type list at %C");
     821              : 
     822            3 : cleanup:
     823            3 :   gfc_free_omp_namelist (head, false, false, false, false);
     824            3 :   gfc_current_locus = old_loc;
     825            3 :   return MATCH_ERROR;
     826              : }
     827              : 
     828              : static match
     829          819 : match_omp_oacc_expr_list (const char *str, gfc_expr_list **list,
     830              :                           bool allow_asterisk, bool is_omp)
     831              : {
     832          819 :   gfc_expr_list *head, *tail, *p;
     833          819 :   locus old_loc;
     834          819 :   gfc_expr *expr;
     835          819 :   match m;
     836              : 
     837          819 :   head = tail = NULL;
     838              : 
     839          819 :   old_loc = gfc_current_locus;
     840              : 
     841          819 :   m = gfc_match (str);
     842          819 :   if (m != MATCH_YES)
     843              :     return m;
     844              : 
     845         1030 :   for (;;)
     846              :     {
     847         1030 :       m = gfc_match_expr (&expr);
     848         1030 :       if (m == MATCH_YES || allow_asterisk)
     849              :         {
     850         1018 :           p = gfc_get_expr_list ();
     851         1018 :           if (head == NULL)
     852              :             head = tail = p;
     853              :           else
     854              :             {
     855          335 :               tail->next = p;
     856          335 :               tail = tail->next;
     857              :             }
     858         1018 :           if (m == MATCH_YES)
     859          885 :             tail->expr = expr;
     860          133 :           else if (gfc_match (" *") != MATCH_YES)
     861           18 :             goto syntax;
     862         1000 :           goto next_item;
     863              :         }
     864           12 :       if (m == MATCH_ERROR)
     865            0 :         goto cleanup;
     866           12 :       goto syntax;
     867              : 
     868         1000 :     next_item:
     869         1000 :       if (gfc_match_char (')') == MATCH_YES)
     870              :         break;
     871          346 :       if (gfc_match_char (',') != MATCH_YES)
     872            6 :         goto syntax;
     873              :     }
     874              : 
     875          660 :   while (*list)
     876            6 :     list = &(*list)->next;
     877              : 
     878          654 :   *list = head;
     879          654 :   return MATCH_YES;
     880              : 
     881           36 : syntax:
     882           36 :   if (is_omp)
     883            7 :     gfc_error ("Syntax error in OpenMP expression list at %C");
     884              :   else
     885           29 :     gfc_error ("Syntax error in OpenACC expression list at %C");
     886              : 
     887           36 : cleanup:
     888           36 :   gfc_free_expr_list (head);
     889           36 :   gfc_current_locus = old_loc;
     890           36 :   return MATCH_ERROR;
     891              : }
     892              : 
     893              : static match
     894         3055 : match_oacc_clause_gwv (gfc_omp_clauses *cp, unsigned gwv)
     895              : {
     896         3055 :   match ret = MATCH_YES;
     897              : 
     898         3055 :   if (gfc_match (" ( ") != MATCH_YES)
     899              :     return MATCH_NO;
     900              : 
     901          470 :   if (gwv == GOMP_DIM_GANG)
     902              :     {
     903              :         /* The gang clause accepts two optional arguments, num and static.
     904              :          The num argument may either be explicit (num: <val>) or
     905              :          implicit without (<val> without num:).  */
     906              : 
     907          457 :       while (ret == MATCH_YES)
     908              :         {
     909          236 :           if (gfc_match (" static :") == MATCH_YES)
     910              :             {
     911          114 :               if (cp->gang_static)
     912              :                 return MATCH_ERROR;
     913              :               else
     914          113 :                 cp->gang_static = true;
     915          113 :               if (gfc_match_char ('*') == MATCH_YES)
     916           18 :                 cp->gang_static_expr = NULL;
     917           95 :               else if (gfc_match (" %e ", &cp->gang_static_expr) != MATCH_YES)
     918              :                 return MATCH_ERROR;
     919              :             }
     920              :           else
     921              :             {
     922          122 :               if (cp->gang_num_expr)
     923              :                 return MATCH_ERROR;
     924              : 
     925              :               /* The 'num' argument is optional.  */
     926          121 :               gfc_match (" num :");
     927              : 
     928          121 :               if (gfc_match (" %e ", &cp->gang_num_expr) != MATCH_YES)
     929              :                 return MATCH_ERROR;
     930              :             }
     931              : 
     932          231 :           ret = gfc_match (" , ");
     933              :         }
     934              :     }
     935          244 :   else if (gwv == GOMP_DIM_WORKER)
     936              :     {
     937              :       /* The 'num' argument is optional.  */
     938          107 :       gfc_match (" num :");
     939              : 
     940          107 :       if (gfc_match (" %e ", &cp->worker_expr) != MATCH_YES)
     941              :         return MATCH_ERROR;
     942              :     }
     943          137 :   else if (gwv == GOMP_DIM_VECTOR)
     944              :     {
     945              :       /* The 'length' argument is optional.  */
     946          137 :       gfc_match (" length :");
     947              : 
     948          137 :       if (gfc_match (" %e ", &cp->vector_expr) != MATCH_YES)
     949              :         return MATCH_ERROR;
     950              :     }
     951              :   else
     952            0 :     gfc_fatal_error ("Unexpected OpenACC parallelism.");
     953              : 
     954          459 :   return gfc_match (" )");
     955              : }
     956              : 
     957              : static match
     958            8 : gfc_match_oacc_clause_link (const char *str, gfc_omp_namelist **list)
     959              : {
     960            8 :   gfc_omp_namelist *head = NULL;
     961            8 :   gfc_omp_namelist *tail, *p;
     962            8 :   locus old_loc;
     963            8 :   char n[GFC_MAX_SYMBOL_LEN+1];
     964            8 :   gfc_symbol *sym;
     965            8 :   match m;
     966            8 :   gfc_symtree *st;
     967              : 
     968            8 :   old_loc = gfc_current_locus;
     969              : 
     970            8 :   m = gfc_match (str);
     971            8 :   if (m != MATCH_YES)
     972              :     return m;
     973              : 
     974            8 :   m = gfc_match (" (");
     975              : 
     976           14 :   for (;;)
     977              :     {
     978           14 :       m = gfc_match_symbol (&sym, 0);
     979           14 :       switch (m)
     980              :         {
     981            8 :         case MATCH_YES:
     982            8 :           if (sym->attr.in_common)
     983              :             {
     984            2 :               gfc_error_now ("Variable at %C is an element of a COMMON block");
     985            2 :               goto cleanup;
     986              :             }
     987            6 :           gfc_set_sym_referenced (sym);
     988            6 :           p = gfc_get_omp_namelist ();
     989            6 :           if (head == NULL)
     990              :             head = tail = p;
     991              :           else
     992              :             {
     993            4 :               tail->next = p;
     994            4 :               tail = tail->next;
     995              :             }
     996            6 :           tail->sym = sym;
     997            6 :           tail->expr = NULL;
     998            6 :           tail->where = gfc_current_locus;
     999            6 :           goto next_item;
    1000              :         case MATCH_NO:
    1001              :           break;
    1002              : 
    1003            0 :         case MATCH_ERROR:
    1004            0 :           goto cleanup;
    1005              :         }
    1006              : 
    1007            6 :       m = gfc_match (" / %n /", n);
    1008            6 :       if (m == MATCH_ERROR)
    1009            0 :         goto cleanup;
    1010            6 :       if (m == MATCH_NO || n[0] == '\0')
    1011            0 :         goto syntax;
    1012              : 
    1013            6 :       st = gfc_find_symtree (gfc_current_ns->common_root, n);
    1014            6 :       if (st == NULL)
    1015              :         {
    1016            1 :           gfc_error ("COMMON block /%s/ not found at %C", n);
    1017            1 :           goto cleanup;
    1018              :         }
    1019              : 
    1020           20 :       for (sym = st->n.common->head; sym; sym = sym->common_next)
    1021              :         {
    1022           15 :           gfc_set_sym_referenced (sym);
    1023           15 :           p = gfc_get_omp_namelist ();
    1024           15 :           if (head == NULL)
    1025              :             head = tail = p;
    1026              :           else
    1027              :             {
    1028           12 :               tail->next = p;
    1029           12 :               tail = tail->next;
    1030              :             }
    1031           15 :           tail->sym = sym;
    1032           15 :           tail->where = gfc_current_locus;
    1033              :         }
    1034              : 
    1035            5 :     next_item:
    1036           11 :       if (gfc_match_char (')') == MATCH_YES)
    1037              :         break;
    1038            6 :       if (gfc_match_char (',') != MATCH_YES)
    1039            0 :         goto syntax;
    1040              :     }
    1041              : 
    1042            5 :   if (gfc_match_omp_eos () != MATCH_YES)
    1043              :     {
    1044            1 :       gfc_error ("Unexpected junk after !$ACC DECLARE at %C");
    1045            1 :       goto cleanup;
    1046              :     }
    1047              : 
    1048            4 :   while (*list)
    1049            0 :     list = &(*list)->next;
    1050            4 :   *list = head;
    1051            4 :   return MATCH_YES;
    1052              : 
    1053            0 : syntax:
    1054            0 :   gfc_error ("Syntax error in !$ACC DECLARE list at %C");
    1055              : 
    1056            4 : cleanup:
    1057            4 :   gfc_current_locus = old_loc;
    1058            4 :   return MATCH_ERROR;
    1059              : }
    1060              : 
    1061              : /* OpenMP clauses.  */
    1062              : enum omp_mask1
    1063              : {
    1064              :   OMP_CLAUSE_PRIVATE,
    1065              :   OMP_CLAUSE_FIRSTPRIVATE,
    1066              :   OMP_CLAUSE_LASTPRIVATE,
    1067              :   OMP_CLAUSE_COPYPRIVATE,
    1068              :   OMP_CLAUSE_SHARED,
    1069              :   OMP_CLAUSE_COPYIN,
    1070              :   OMP_CLAUSE_REDUCTION,
    1071              :   OMP_CLAUSE_IN_REDUCTION,
    1072              :   OMP_CLAUSE_TASK_REDUCTION,
    1073              :   OMP_CLAUSE_IF,
    1074              :   OMP_CLAUSE_NUM_THREADS,
    1075              :   OMP_CLAUSE_SCHEDULE,
    1076              :   OMP_CLAUSE_DEFAULT,
    1077              :   OMP_CLAUSE_ORDER,
    1078              :   OMP_CLAUSE_ORDERED,
    1079              :   OMP_CLAUSE_COLLAPSE,
    1080              :   OMP_CLAUSE_UNTIED,
    1081              :   OMP_CLAUSE_FINAL,
    1082              :   OMP_CLAUSE_MERGEABLE,
    1083              :   OMP_CLAUSE_ALIGNED,
    1084              :   OMP_CLAUSE_DEPEND,
    1085              :   OMP_CLAUSE_INBRANCH,
    1086              :   OMP_CLAUSE_LINEAR,
    1087              :   OMP_CLAUSE_NOTINBRANCH,
    1088              :   OMP_CLAUSE_PROC_BIND,
    1089              :   OMP_CLAUSE_SAFELEN,
    1090              :   OMP_CLAUSE_SIMDLEN,
    1091              :   OMP_CLAUSE_UNIFORM,
    1092              :   OMP_CLAUSE_DEVICE,
    1093              :   OMP_CLAUSE_MAP,
    1094              :   OMP_CLAUSE_TO,
    1095              :   OMP_CLAUSE_FROM,
    1096              :   OMP_CLAUSE_NUM_TEAMS,
    1097              :   OMP_CLAUSE_THREAD_LIMIT,
    1098              :   OMP_CLAUSE_DIST_SCHEDULE,
    1099              :   OMP_CLAUSE_DEFAULTMAP,
    1100              :   OMP_CLAUSE_GRAINSIZE,
    1101              :   OMP_CLAUSE_HINT,
    1102              :   OMP_CLAUSE_IS_DEVICE_PTR,
    1103              :   OMP_CLAUSE_LINK,
    1104              :   OMP_CLAUSE_NOGROUP,
    1105              :   OMP_CLAUSE_NOTEMPORAL,
    1106              :   OMP_CLAUSE_NUM_TASKS,
    1107              :   OMP_CLAUSE_PRIORITY,
    1108              :   OMP_CLAUSE_SIMD,
    1109              :   OMP_CLAUSE_THREADS,
    1110              :   OMP_CLAUSE_USE_DEVICE_PTR,
    1111              :   OMP_CLAUSE_USE_DEVICE_ADDR,  /* OpenMP 5.0.  */
    1112              :   OMP_CLAUSE_DEVICE_TYPE,  /* OpenMP 5.0.  */
    1113              :   OMP_CLAUSE_ATOMIC,  /* OpenMP 5.0.  */
    1114              :   OMP_CLAUSE_CAPTURE,  /* OpenMP 5.0.  */
    1115              :   OMP_CLAUSE_MEMORDER,  /* OpenMP 5.0.  */
    1116              :   OMP_CLAUSE_DETACH,  /* OpenMP 5.0.  */
    1117              :   OMP_CLAUSE_AFFINITY,  /* OpenMP 5.0.  */
    1118              :   OMP_CLAUSE_ALLOCATE,  /* OpenMP 5.0.  */
    1119              :   OMP_CLAUSE_BIND,  /* OpenMP 5.0.  */
    1120              :   OMP_CLAUSE_FILTER,  /* OpenMP 5.1.  */
    1121              :   OMP_CLAUSE_AT,  /* OpenMP 5.1.  */
    1122              :   OMP_CLAUSE_MESSAGE,  /* OpenMP 5.1.  */
    1123              :   OMP_CLAUSE_SEVERITY,  /* OpenMP 5.1.  */
    1124              :   OMP_CLAUSE_COMPARE,  /* OpenMP 5.1.  */
    1125              :   OMP_CLAUSE_FAIL,  /* OpenMP 5.1.  */
    1126              :   OMP_CLAUSE_WEAK,  /* OpenMP 5.1.  */
    1127              :   OMP_CLAUSE_NOWAIT,
    1128              :   /* This must come last.  */
    1129              :   OMP_MASK1_LAST
    1130              : };
    1131              : 
    1132              : /* More OpenMP clauses and OpenACC 2.0+ specific clauses. */
    1133              : enum omp_mask2
    1134              : {
    1135              :   OMP_CLAUSE_ASYNC,
    1136              :   OMP_CLAUSE_NUM_GANGS,
    1137              :   OMP_CLAUSE_NUM_WORKERS,
    1138              :   OMP_CLAUSE_VECTOR_LENGTH,
    1139              :   OMP_CLAUSE_COPY,
    1140              :   OMP_CLAUSE_COPYOUT,
    1141              :   OMP_CLAUSE_CREATE,
    1142              :   OMP_CLAUSE_NO_CREATE,
    1143              :   OMP_CLAUSE_PRESENT,
    1144              :   OMP_CLAUSE_DEVICEPTR,
    1145              :   OMP_CLAUSE_GANG,
    1146              :   OMP_CLAUSE_WORKER,
    1147              :   OMP_CLAUSE_VECTOR,
    1148              :   OMP_CLAUSE_SEQ,
    1149              :   OMP_CLAUSE_INDEPENDENT,
    1150              :   OMP_CLAUSE_USE_DEVICE,
    1151              :   OMP_CLAUSE_DEVICE_RESIDENT,
    1152              :   OMP_CLAUSE_SELF,
    1153              :   OMP_CLAUSE_HOST,
    1154              :   OMP_CLAUSE_WAIT,
    1155              :   OMP_CLAUSE_DELETE,
    1156              :   OMP_CLAUSE_AUTO,
    1157              :   OMP_CLAUSE_TILE,
    1158              :   OMP_CLAUSE_IF_PRESENT,
    1159              :   OMP_CLAUSE_FINALIZE,
    1160              :   OMP_CLAUSE_ATTACH,
    1161              :   OMP_CLAUSE_NOHOST,
    1162              :   OMP_CLAUSE_HAS_DEVICE_ADDR,  /* OpenMP 5.1  */
    1163              :   OMP_CLAUSE_ENTER, /* OpenMP 5.2 */
    1164              :   OMP_CLAUSE_DOACROSS, /* OpenMP 5.2 */
    1165              :   OMP_CLAUSE_ASSUMPTIONS, /* OpenMP 5.1. */
    1166              :   OMP_CLAUSE_USES_ALLOCATORS, /* OpenMP 5.0  */
    1167              :   OMP_CLAUSE_INDIRECT, /* OpenMP 5.1  */
    1168              :   OMP_CLAUSE_FULL,  /* OpenMP 5.1.  */
    1169              :   OMP_CLAUSE_PARTIAL,  /* OpenMP 5.1.  */
    1170              :   OMP_CLAUSE_SIZES,  /* OpenMP 5.1.  */
    1171              :   OMP_CLAUSE_INIT,  /* OpenMP 5.1.  */
    1172              :   OMP_CLAUSE_DESTROY,  /* OpenMP 5.1.  */
    1173              :   OMP_CLAUSE_USE,  /* OpenMP 5.1.  */
    1174              :   OMP_CLAUSE_NOVARIANTS, /* OpenMP 5.1  */
    1175              :   OMP_CLAUSE_NOCONTEXT, /* OpenMP 5.1  */
    1176              :   OMP_CLAUSE_INTEROP, /* OpenMP 5.1  */
    1177              :   OMP_CLAUSE_LOCAL, /* OpenMP 6.0 */
    1178              :   OMP_CLAUSE_DYN_GROUPPRIVATE, /* OpenMP 6.1 */
    1179              :   /* This must come last.  */
    1180              :   OMP_MASK2_LAST
    1181              : };
    1182              : 
    1183              : struct omp_inv_mask;
    1184              : 
    1185              : /* Customized bitset for up to 128-bits.
    1186              :    The two enums above provide bit numbers to use, and which of the
    1187              :    two enums it is determines which of the two mask fields is used.
    1188              :    Supported operations are defining a mask, like:
    1189              :    #define XXX_CLAUSES \
    1190              :      (omp_mask (OMP_CLAUSE_XXX) | OMP_CLAUSE_YYY | OMP_CLAUSE_ZZZ)
    1191              :    oring such bitsets together or removing selected bits:
    1192              :    (XXX_CLAUSES | YYY_CLAUSES) & ~(omp_mask (OMP_CLAUSE_VVV))
    1193              :    and testing individual bits:
    1194              :    if (mask & OMP_CLAUSE_UUU)  */
    1195              : 
    1196              : struct omp_mask {
    1197              :   const uint64_t mask1;
    1198              :   const uint64_t mask2;
    1199              :   inline omp_mask ();
    1200              :   inline omp_mask (omp_mask1);
    1201              :   inline omp_mask (omp_mask2);
    1202              :   inline omp_mask (uint64_t, uint64_t);
    1203              :   inline omp_mask operator| (omp_mask1) const;
    1204              :   inline omp_mask operator| (omp_mask2) const;
    1205              :   inline omp_mask operator| (omp_mask) const;
    1206              :   inline omp_mask operator& (const omp_inv_mask &) const;
    1207              :   inline bool operator& (omp_mask1) const;
    1208              :   inline bool operator& (omp_mask2) const;
    1209              :   inline omp_inv_mask operator~ () const;
    1210              : };
    1211              : 
    1212              : struct omp_inv_mask : public omp_mask {
    1213              :   inline omp_inv_mask (const omp_mask &);
    1214              : };
    1215              : 
    1216              : omp_mask::omp_mask () : mask1 (0), mask2 (0)
    1217              : {
    1218              : }
    1219              : 
    1220        31878 : omp_mask::omp_mask (omp_mask1 m) : mask1 (((uint64_t) 1) << m), mask2 (0)
    1221              : {
    1222              : }
    1223              : 
    1224         2203 : omp_mask::omp_mask (omp_mask2 m) : mask1 (0), mask2 (((uint64_t) 1) << m)
    1225              : {
    1226              : }
    1227              : 
    1228        32784 : omp_mask::omp_mask (uint64_t m1, uint64_t m2) : mask1 (m1), mask2 (m2)
    1229              : {
    1230              : }
    1231              : 
    1232              : omp_mask
    1233        31833 : omp_mask::operator| (omp_mask1 m) const
    1234              : {
    1235        31833 :   return omp_mask (mask1 | (((uint64_t) 1) << m), mask2);
    1236              : }
    1237              : 
    1238              : omp_mask
    1239        16572 : omp_mask::operator| (omp_mask2 m) const
    1240              : {
    1241        16572 :   return omp_mask (mask1, mask2 | (((uint64_t) 1) << m));
    1242              : }
    1243              : 
    1244              : omp_mask
    1245         4348 : omp_mask::operator| (omp_mask m) const
    1246              : {
    1247         4348 :   return omp_mask (mask1 | m.mask1, mask2 | m.mask2);
    1248              : }
    1249              : 
    1250              : omp_mask
    1251         2009 : omp_mask::operator& (const omp_inv_mask &m) const
    1252              : {
    1253         2009 :   return omp_mask (mask1 & ~m.mask1, mask2 & ~m.mask2);
    1254              : }
    1255              : 
    1256              : bool
    1257       124497 : omp_mask::operator& (omp_mask1 m) const
    1258              : {
    1259       124497 :   return (mask1 & (((uint64_t) 1) << m)) != 0;
    1260              : }
    1261              : 
    1262              : bool
    1263        88072 : omp_mask::operator& (omp_mask2 m) const
    1264              : {
    1265        88072 :   return (mask2 & (((uint64_t) 1) << m)) != 0;
    1266              : }
    1267              : 
    1268              : omp_inv_mask
    1269         2009 : omp_mask::operator~ () const
    1270              : {
    1271         2009 :   return omp_inv_mask (*this);
    1272              : }
    1273              : 
    1274         2009 : omp_inv_mask::omp_inv_mask (const omp_mask &m) : omp_mask (m)
    1275              : {
    1276              : }
    1277              : 
    1278              : /* Helper function for OpenACC and OpenMP clauses involving memory
    1279              :    mapping.  */
    1280              : 
    1281              : static bool
    1282         5539 : gfc_match_omp_map_clause (gfc_omp_namelist **list, gfc_omp_map_op map_op,
    1283              :                           bool allow_common, bool allow_derived)
    1284              : {
    1285         5539 :   gfc_omp_namelist **head = NULL;
    1286         5539 :   if (gfc_match_omp_variable_list ("", list, allow_common, NULL, &head, true,
    1287              :                                    allow_derived)
    1288              :       == MATCH_YES)
    1289              :     {
    1290         5530 :       gfc_omp_namelist *n;
    1291        13395 :       for (n = *head; n; n = n->next)
    1292         7865 :         n->u.map.op = map_op;
    1293              :       return true;
    1294              :     }
    1295              : 
    1296              :   return false;
    1297              : }
    1298              : 
    1299              : static match
    1300         1111 : gfc_match_iterator (gfc_namespace **ns, bool permit_var)
    1301              : {
    1302         1111 :   locus old_loc = gfc_current_locus;
    1303              : 
    1304         1111 :   if (gfc_match ("iterator ( ") != MATCH_YES)
    1305              :     return MATCH_NO;
    1306              : 
    1307           77 :   gfc_typespec ts;
    1308           77 :   gfc_symbol *last = NULL;
    1309           77 :   gfc_expr *begin, *end, *step;
    1310           77 :   *ns = gfc_build_block_ns (gfc_current_ns);
    1311           83 :   char name[GFC_MAX_SYMBOL_LEN + 1];
    1312           89 :   while (true)
    1313              :     {
    1314           83 :       locus prev_loc = gfc_current_locus;
    1315           83 :       if (gfc_match_type_spec (&ts) == MATCH_YES
    1316           83 :           && gfc_match (" :: ") == MATCH_YES)
    1317              :         {
    1318            5 :           if (ts.type != BT_INTEGER)
    1319              :             {
    1320            2 :               gfc_error ("Expected INTEGER type at %L", &prev_loc);
    1321            5 :               return MATCH_ERROR;
    1322              :             }
    1323              :           permit_var = false;
    1324              :         }
    1325              :       else
    1326              :         {
    1327           78 :           ts.type = BT_INTEGER;
    1328           78 :           ts.kind = gfc_default_integer_kind;
    1329           78 :           gfc_current_locus = prev_loc;
    1330              :         }
    1331           81 :       prev_loc = gfc_current_locus;
    1332           81 :       if (gfc_match_name (name) != MATCH_YES)
    1333              :         {
    1334            4 :           gfc_error ("Expected identifier at %C");
    1335            4 :           goto failed;
    1336              :         }
    1337           77 :       if (gfc_find_symtree ((*ns)->sym_root, name))
    1338              :         {
    1339            2 :           gfc_error ("Same identifier %qs specified again at %C", name);
    1340            2 :           goto failed;
    1341              :         }
    1342              : 
    1343           75 :       gfc_symbol *sym = gfc_new_symbol (name, *ns);
    1344           75 :       if (last)
    1345            4 :         last->tlink = sym;
    1346              :       else
    1347           71 :         (*ns)->omp_affinity_iterators = sym;
    1348           75 :       last = sym;
    1349           75 :       sym->declared_at = prev_loc;
    1350           75 :       sym->ts = ts;
    1351           75 :       sym->attr.flavor = FL_VARIABLE;
    1352           75 :       sym->attr.artificial = 1;
    1353           75 :       sym->attr.referenced = 1;
    1354           75 :       sym->refs++;
    1355           75 :       gfc_symtree *st = gfc_new_symtree (&(*ns)->sym_root, name);
    1356           75 :       st->n.sym = sym;
    1357              : 
    1358           75 :       prev_loc = gfc_current_locus;
    1359           75 :       if (gfc_match (" = ") != MATCH_YES)
    1360            3 :         goto failed;
    1361           72 :       permit_var = false;
    1362           72 :       begin = end = step = NULL;
    1363           72 :       if (gfc_match ("%e : ", &begin) != MATCH_YES
    1364           72 :           || gfc_match ("%e ", &end) != MATCH_YES)
    1365              :         {
    1366            3 :           gfc_error ("Expected range-specification at %C");
    1367            3 :           gfc_free_expr (begin);
    1368            3 :           gfc_free_expr (end);
    1369            3 :           return MATCH_ERROR;
    1370              :         }
    1371           69 :       if (':' == gfc_peek_ascii_char ())
    1372              :         {
    1373           23 :           if (gfc_match (": %e ", &step) != MATCH_YES)
    1374              :             {
    1375            5 :               gfc_free_expr (begin);
    1376            5 :               gfc_free_expr (end);
    1377            5 :               gfc_free_expr (step);
    1378            5 :               goto failed;
    1379              :             }
    1380              :         }
    1381              : 
    1382           64 :       gfc_expr *e = gfc_get_expr ();
    1383           64 :       e->where = prev_loc;
    1384           64 :       e->expr_type = EXPR_ARRAY;
    1385           64 :       e->ts = ts;
    1386           64 :       e->rank = 1;
    1387           64 :       e->shape = gfc_get_shape (1);
    1388          110 :       mpz_init_set_ui (e->shape[0], step ? 3 : 2);
    1389           64 :       gfc_constructor_append_expr (&e->value.constructor, begin, &begin->where);
    1390           64 :       gfc_constructor_append_expr (&e->value.constructor, end, &end->where);
    1391           64 :       if (step)
    1392           18 :         gfc_constructor_append_expr (&e->value.constructor, step, &step->where);
    1393           64 :       sym->value = e;
    1394              : 
    1395           64 :       if (gfc_match (") ") == MATCH_YES)
    1396              :         break;
    1397            6 :       if (gfc_match (", ") != MATCH_YES)
    1398            0 :         goto failed;
    1399            6 :     }
    1400           58 :   return MATCH_YES;
    1401              : 
    1402           14 : failed:
    1403           14 :   gfc_namespace *prev_ns = NULL;
    1404           14 :   for (gfc_namespace *it = gfc_current_ns->contained; it; it = it->sibling)
    1405              :     {
    1406            0 :       if (it == *ns)
    1407              :         {
    1408            0 :           if (prev_ns)
    1409            0 :             prev_ns->sibling = it->sibling;
    1410              :           else
    1411            0 :             gfc_current_ns->contained = it->sibling;
    1412            0 :           gfc_free_namespace (it);
    1413            0 :           break;
    1414              :         }
    1415            0 :       prev_ns = it;
    1416              :     }
    1417           14 :   *ns = NULL;
    1418           14 :   if (!permit_var)
    1419              :     return MATCH_ERROR;
    1420            4 :   gfc_current_locus = old_loc;
    1421            4 :   return MATCH_NO;
    1422              : }
    1423              : 
    1424              : /* Match target update's to/from( [present:] var-list).  */
    1425              : 
    1426              : static match
    1427         1715 : gfc_match_motion_var_list (const char *str, gfc_omp_namelist **list,
    1428              :                            gfc_omp_namelist ***headp)
    1429              : {
    1430         1715 :   match m = gfc_match (str);
    1431         1715 :   if (m != MATCH_YES)
    1432              :     return m;
    1433              : 
    1434         1715 :   match m_present = gfc_match (" present : ");
    1435              : 
    1436         1715 :   m = gfc_match_omp_variable_list ("", list, false, NULL, headp, true, true);
    1437         1715 :   if (m != MATCH_YES)
    1438              :     return m;
    1439         1715 :   if (m_present == MATCH_YES)
    1440              :     {
    1441            5 :       gfc_omp_namelist *n;
    1442           10 :       for (n = **headp; n; n = n->next)
    1443            5 :         n->u.present_modifier = true;
    1444              :     }
    1445              :   return MATCH_YES;
    1446              : }
    1447              : 
    1448              : /* reduction ( reduction-modifier, reduction-operator : variable-list )
    1449              :    in_reduction ( reduction-operator : variable-list )
    1450              :    task_reduction ( reduction-operator : variable-list )  */
    1451              : 
    1452              : static match
    1453         4356 : gfc_match_omp_clause_reduction (char pc, gfc_omp_clauses *c, bool openacc,
    1454              :                                 bool allow_derived, bool openmp_target = false)
    1455              : {
    1456         4356 :   if (pc == 'r' && gfc_match ("reduction ( ") != MATCH_YES)
    1457              :     return MATCH_NO;
    1458         4356 :   else if (pc == 'i' && gfc_match ("in_reduction ( ") != MATCH_YES)
    1459              :     return MATCH_NO;
    1460         4244 :   else if (pc == 't' && gfc_match ("task_reduction ( ") != MATCH_YES)
    1461              :     return MATCH_NO;
    1462              : 
    1463         4244 :   locus old_loc = gfc_current_locus;
    1464         4244 :   int list_idx = 0;
    1465              : 
    1466         4244 :   if (pc == 'r' && !openacc)
    1467              :     {
    1468         2117 :       if (gfc_match ("inscan") == MATCH_YES)
    1469              :         list_idx = OMP_LIST_REDUCTION_INSCAN;
    1470         2047 :       else if (gfc_match ("task") == MATCH_YES)
    1471              :         list_idx = OMP_LIST_REDUCTION_TASK;
    1472         1943 :       else if (gfc_match ("default") == MATCH_YES)
    1473              :         list_idx = OMP_LIST_REDUCTION;
    1474          230 :       if (list_idx != 0 && gfc_match (", ") != MATCH_YES)
    1475              :         {
    1476            1 :           gfc_error ("Comma expected at %C");
    1477            1 :           gfc_current_locus = old_loc;
    1478            1 :           return MATCH_NO;
    1479              :         }
    1480         2116 :       if (list_idx == 0)
    1481         3831 :         list_idx = OMP_LIST_REDUCTION;
    1482              :     }
    1483         2127 :   else if (pc == 'i')
    1484              :     list_idx = OMP_LIST_IN_REDUCTION;
    1485         2009 :   else if (pc == 't')
    1486              :     list_idx = OMP_LIST_TASK_REDUCTION;
    1487              :   else
    1488         3831 :     list_idx = OMP_LIST_REDUCTION;
    1489              : 
    1490         4243 :   gfc_omp_reduction_op rop = OMP_REDUCTION_NONE;
    1491         4243 :   char buffer[GFC_MAX_SYMBOL_LEN + 3];
    1492         4243 :   if (gfc_match_char ('+') == MATCH_YES)
    1493              :     rop = OMP_REDUCTION_PLUS;
    1494         2223 :   else if (gfc_match_char ('*') == MATCH_YES)
    1495              :     rop = OMP_REDUCTION_TIMES;
    1496         1991 :   else if (gfc_match_char ('-') == MATCH_YES)
    1497              :     {
    1498          171 :       if (!openacc)
    1499           16 :         gfc_warning (OPT_Wdeprecated_openmp,
    1500              :                      "%<-%> operator at %C for reductions deprecated in "
    1501              :                      "OpenMP 5.2");
    1502              :       rop = OMP_REDUCTION_MINUS;
    1503              :     }
    1504         1820 :   else if (gfc_match (".and.") == MATCH_YES)
    1505              :     rop = OMP_REDUCTION_AND;
    1506         1714 :   else if (gfc_match (".or.") == MATCH_YES)
    1507              :     rop = OMP_REDUCTION_OR;
    1508          929 :   else if (gfc_match (".eqv.") == MATCH_YES)
    1509              :     rop = OMP_REDUCTION_EQV;
    1510          831 :   else if (gfc_match (".neqv.") == MATCH_YES)
    1511              :     rop = OMP_REDUCTION_NEQV;
    1512          736 :   if (rop != OMP_REDUCTION_NONE)
    1513         3507 :     snprintf (buffer, sizeof buffer, "operator %s",
    1514              :               gfc_op2string ((gfc_intrinsic_op) rop));
    1515          736 :   else if (gfc_match_defined_op_name (buffer + 1, 1) == MATCH_YES)
    1516              :     {
    1517           38 :       buffer[0] = '.';
    1518           38 :       strcat (buffer, ".");
    1519              :     }
    1520          698 :   else if (gfc_match_name (buffer) == MATCH_YES)
    1521              :     {
    1522          697 :       gfc_symbol *sym;
    1523          697 :       const char *n = buffer;
    1524              : 
    1525          697 :       gfc_find_symbol (buffer, NULL, 1, &sym);
    1526          697 :       if (sym != NULL)
    1527              :         {
    1528          216 :           if (sym->attr.intrinsic)
    1529          139 :             n = sym->name;
    1530           77 :           else if ((sym->attr.flavor != FL_UNKNOWN
    1531           75 :                     && sym->attr.flavor != FL_PROCEDURE)
    1532           75 :                    || sym->attr.external
    1533           64 :                    || sym->attr.generic
    1534           64 :                    || sym->attr.entry
    1535           64 :                    || sym->attr.result
    1536           64 :                    || sym->attr.dummy
    1537           64 :                    || sym->attr.subroutine
    1538           63 :                    || sym->attr.pointer
    1539           63 :                    || sym->attr.target
    1540           63 :                    || sym->attr.cray_pointer
    1541           63 :                    || sym->attr.cray_pointee
    1542           63 :                    || (sym->attr.proc != PROC_UNKNOWN
    1543            1 :                        && sym->attr.proc != PROC_INTRINSIC)
    1544           62 :                    || sym->attr.if_source != IFSRC_UNKNOWN
    1545           62 :                    || sym == sym->ns->proc_name)
    1546              :                 {
    1547              :                   sym = NULL;
    1548              :                   n = NULL;
    1549              :                 }
    1550              :               else
    1551           62 :                 n = sym->name;
    1552              :             }
    1553          201 :           if (n == NULL)
    1554              :             rop = OMP_REDUCTION_NONE;
    1555          682 :           else if (strcmp (n, "max") == 0)
    1556              :             rop = OMP_REDUCTION_MAX;
    1557          517 :           else if (strcmp (n, "min") == 0)
    1558              :             rop = OMP_REDUCTION_MIN;
    1559          376 :           else if (strcmp (n, "iand") == 0)
    1560              :             rop = OMP_REDUCTION_IAND;
    1561          321 :           else if (strcmp (n, "ior") == 0)
    1562              :             rop = OMP_REDUCTION_IOR;
    1563          255 :           else if (strcmp (n, "ieor") == 0)
    1564              :             rop = OMP_REDUCTION_IEOR;
    1565              :           if (rop != OMP_REDUCTION_NONE
    1566          477 :               && sym != NULL
    1567          200 :               && ! sym->attr.intrinsic
    1568           61 :               && ! sym->attr.use_assoc
    1569           61 :               && ((sym->attr.flavor == FL_UNKNOWN
    1570            2 :                    && !gfc_add_flavor (&sym->attr, FL_PROCEDURE,
    1571              :                                               sym->name, NULL))
    1572           61 :                   || !gfc_add_intrinsic (&sym->attr, NULL)))
    1573              :             rop = OMP_REDUCTION_NONE;
    1574              :     }
    1575              :   else
    1576            1 :     buffer[0] = '\0';
    1577         4243 :   gfc_omp_udr *udr = (buffer[0] ? gfc_find_omp_udr (gfc_current_ns, buffer, NULL)
    1578              :                                 : NULL);
    1579         4243 :   gfc_omp_namelist **head = NULL;
    1580         4243 :   if (rop == OMP_REDUCTION_NONE && udr)
    1581          250 :     rop = OMP_REDUCTION_USER;
    1582              : 
    1583         4243 :   if (gfc_match_omp_variable_list (" :", &c->lists[list_idx], false, NULL,
    1584              :                                    &head, openacc, allow_derived) != MATCH_YES)
    1585              :     {
    1586            9 :       gfc_current_locus = old_loc;
    1587            9 :       return MATCH_NO;
    1588              :     }
    1589         4234 :   gfc_omp_namelist *n;
    1590         4234 :   if (rop == OMP_REDUCTION_NONE)
    1591              :     {
    1592            6 :       n = *head;
    1593            6 :       *head = NULL;
    1594            6 :       gfc_error_now ("!$OMP DECLARE REDUCTION %s not found at %L",
    1595              :                      buffer, &old_loc);
    1596            6 :       gfc_free_omp_namelist (n, false, false, false, false);
    1597              :     }
    1598              :   else
    1599         9108 :     for (n = *head; n; n = n->next)
    1600              :       {
    1601         4880 :         n->u.reduction_op = rop;
    1602         4880 :         if (udr)
    1603              :           {
    1604          473 :             n->u2.udr = gfc_get_omp_namelist_udr ();
    1605          473 :             n->u2.udr->udr = udr;
    1606              :           }
    1607         4880 :         if (openmp_target && list_idx == OMP_LIST_IN_REDUCTION)
    1608              :           {
    1609           40 :             gfc_omp_namelist *p = gfc_get_omp_namelist (), **tl;
    1610           40 :             p->sym = n->sym;
    1611           40 :             p->where = n->where;
    1612           40 :             p->u.map.op = OMP_MAP_ALWAYS_TOFROM;
    1613              : 
    1614           40 :             tl = &c->lists[OMP_LIST_MAP];
    1615           52 :             while (*tl)
    1616           12 :               tl = &((*tl)->next);
    1617           40 :             *tl = p;
    1618           40 :             p->next = NULL;
    1619              :           }
    1620              :      }
    1621              :   return MATCH_YES;
    1622              : }
    1623              : 
    1624              : static match
    1625           39 : gfc_omp_absent_contains_clause (gfc_omp_assumptions **assume, bool is_absent)
    1626              : {
    1627           39 :   if (*assume == NULL)
    1628           14 :     *assume = gfc_get_omp_assumptions ();
    1629           61 :   do
    1630              :     {
    1631           50 :       gfc_statement st = ST_NONE;
    1632           50 :       gfc_gobble_whitespace ();
    1633           50 :       locus old_loc = gfc_current_locus;
    1634           50 :       char c = gfc_peek_ascii_char ();
    1635           50 :       enum gfc_omp_directive_kind kind
    1636              :         = GFC_OMP_DIR_DECLARATIVE; /* Silence warning. */
    1637         1524 :       for (size_t i = 0; i < ARRAY_SIZE (gfc_omp_directives); i++)
    1638              :         {
    1639         1524 :           if (gfc_omp_directives[i].name[0] > c)
    1640              :             break;
    1641         1474 :           if (gfc_omp_directives[i].name[0] != c)
    1642         1135 :             continue;
    1643          339 :           if (gfc_match (gfc_omp_directives[i].name) == MATCH_YES)
    1644              :             {
    1645           50 :               st = gfc_omp_directives[i].st;
    1646           50 :               kind = gfc_omp_directives[i].kind;
    1647              :             }
    1648              :         }
    1649           50 :       gfc_gobble_whitespace ();
    1650           50 :       c = gfc_peek_ascii_char ();
    1651           50 :       if (st == ST_NONE || (c != ',' && c != ')'))
    1652              :         {
    1653            0 :           if (st == ST_NONE)
    1654            0 :             gfc_error ("Unknown directive at %L", &old_loc);
    1655              :           else
    1656            0 :             gfc_error ("Invalid combined or composite directive at %L",
    1657              :                        &old_loc);
    1658            3 :           return MATCH_ERROR;
    1659              :         }
    1660           50 :       if (kind == GFC_OMP_DIR_DECLARATIVE
    1661           50 :           || kind == GFC_OMP_DIR_INFORMATIONAL
    1662              :           || kind == GFC_OMP_DIR_META)
    1663              :         {
    1664            3 :           gfc_error ("Invalid %qs directive at %L in %s clause: declarative, "
    1665              :                      "informational, and meta directives not permitted",
    1666              :                      gfc_ascii_statement (st, true), &old_loc,
    1667              :                      is_absent ? "ABSENT" : "CONTAINS");
    1668            3 :           return MATCH_ERROR;
    1669              :         }
    1670           47 :       if (is_absent)
    1671              :         {
    1672              :           /* Use exponential allocation; equivalent to pow2p(x). */
    1673           33 :           int i = (*assume)->n_absent;
    1674           33 :           int size = ((i == 0) ? 4
    1675           10 :                       : pow2p_hwi (i) == 1 ? i*2 : 0);
    1676            8 :           if (size != 0)
    1677           31 :             (*assume)->absent = XRESIZEVEC (gfc_statement,
    1678              :                                             (*assume)->absent, size);
    1679           33 :           (*assume)->absent[(*assume)->n_absent++] = st;
    1680              :         }
    1681              :       else
    1682              :         {
    1683           14 :           int i = (*assume)->n_contains;
    1684           14 :           int size = ((i == 0) ? 4
    1685            4 :                       : pow2p_hwi (i) == 1 ? i*2 : 0);
    1686            4 :           if (size != 0)
    1687           14 :             (*assume)->contains = XRESIZEVEC (gfc_statement,
    1688              :                                               (*assume)->contains, size);
    1689           14 :           (*assume)->contains[(*assume)->n_contains++] = st;
    1690              :         }
    1691           47 :       gfc_gobble_whitespace ();
    1692           47 :       if (gfc_match(",") == MATCH_YES)
    1693           11 :         continue;
    1694           36 :       if (gfc_match(")") == MATCH_YES)
    1695              :         break;
    1696            0 :       gfc_error ("Expected %<,%> or %<)%> at %C");
    1697            0 :       return MATCH_ERROR;
    1698              :     }
    1699              :   while (true);
    1700              : 
    1701           36 :   return MATCH_YES;
    1702              : }
    1703              : 
    1704              : /* Check 'check' argument for duplicated statements in absent and/or contains
    1705              :    clauses. If 'merge', merge them from check to 'merge'.  */
    1706              : 
    1707              : static match
    1708           43 : omp_verify_merge_absent_contains (gfc_statement st, gfc_omp_assumptions *check,
    1709              :                                   gfc_omp_assumptions *merge, locus *loc)
    1710              : {
    1711           43 :   if (check == NULL)
    1712              :     return MATCH_YES;
    1713           43 :   bitmap_head absent_head, contains_head;
    1714           43 :   bitmap_obstack_initialize (NULL);
    1715           43 :   bitmap_initialize (&absent_head, &bitmap_default_obstack);
    1716           43 :   bitmap_initialize (&contains_head, &bitmap_default_obstack);
    1717              : 
    1718           43 :   match m = MATCH_YES;
    1719           76 :   for (int i = 0; i < check->n_absent; i++)
    1720           33 :     if (!bitmap_set_bit (&absent_head, check->absent[i]))
    1721              :       {
    1722            2 :         gfc_error ("%qs directive mentioned multiple times in %s clause in %s "
    1723              :                    "directive at %L",
    1724            2 :                    gfc_ascii_statement (check->absent[i], true),
    1725              :                    "ABSENT", gfc_ascii_statement (st), loc);
    1726            2 :         m = MATCH_ERROR;
    1727              :       }
    1728           57 :   for (int i = 0; i < check->n_contains; i++)
    1729              :     {
    1730           14 :       if (!bitmap_set_bit (&contains_head, check->contains[i]))
    1731              :         {
    1732            2 :           gfc_error ("%qs directive mentioned multiple times in %s clause in %s "
    1733              :                      "directive at %L",
    1734            2 :                      gfc_ascii_statement (check->contains[i], true),
    1735              :                      "CONTAINS", gfc_ascii_statement (st), loc);
    1736            2 :           m = MATCH_ERROR;
    1737              :         }
    1738           14 :       if (bitmap_bit_p (&absent_head, check->contains[i]))
    1739              :         {
    1740            2 :           gfc_error ("%qs directive mentioned both times in ABSENT and CONTAINS "
    1741              :                      "clauses in %s directive at %L",
    1742            2 :                      gfc_ascii_statement (check->absent[i], true),
    1743              :                      gfc_ascii_statement (st), loc);
    1744            2 :           m = MATCH_ERROR;
    1745              :         }
    1746              :     }
    1747              : 
    1748           43 :   if (m == MATCH_ERROR)
    1749              :     return MATCH_ERROR;
    1750           37 :   if (merge == NULL)
    1751              :     return MATCH_YES;
    1752            2 :   if (merge->absent == NULL && check->absent)
    1753              :     {
    1754            1 :       merge->n_absent = check->n_absent;
    1755            1 :       merge->absent = check->absent;
    1756            1 :       check->absent = NULL;
    1757              :     }
    1758            1 :   else if (merge->absent && check->absent)
    1759              :     {
    1760            0 :       check->absent = XRESIZEVEC (gfc_statement, check->absent,
    1761              :                                   merge->n_absent + check->n_absent);
    1762            0 :       for (int i = 0; i < merge->n_absent; i++)
    1763            0 :         if (!bitmap_bit_p (&absent_head, merge->absent[i]))
    1764            0 :           check->absent[check->n_absent++] = merge->absent[i];
    1765            0 :       free (merge->absent);
    1766            0 :       merge->absent = check->absent;
    1767            0 :       merge->n_absent = check->n_absent;
    1768            0 :       check->absent = NULL;
    1769              :     }
    1770            2 :   if (merge->contains == NULL && check->contains)
    1771              :     {
    1772            0 :       merge->n_contains = check->n_contains;
    1773            0 :       merge->contains = check->contains;
    1774            0 :       check->contains = NULL;
    1775              :     }
    1776            2 :   else if (merge->contains && check->contains)
    1777              :     {
    1778            0 :       check->contains = XRESIZEVEC (gfc_statement, check->contains,
    1779              :                                     merge->n_contains + check->n_contains);
    1780            0 :       for (int i = 0; i < merge->n_contains; i++)
    1781            0 :         if (!bitmap_bit_p (&contains_head, merge->contains[i]))
    1782            0 :           check->contains[check->n_contains++] = merge->contains[i];
    1783            0 :       free (merge->contains);
    1784            0 :       merge->contains = check->contains;
    1785            0 :       merge->n_contains = check->n_contains;
    1786            0 :       check->contains = NULL;
    1787              :     }
    1788              :   return MATCH_YES;
    1789              : }
    1790              : 
    1791              : /* OpenMP 5.0
    1792              :    uses_allocators ( allocator-list )
    1793              : 
    1794              :    allocator:
    1795              :      predefined-allocator
    1796              :      variable ( traits-array )
    1797              : 
    1798              :    OpenMP 5.2 deprecated, 6.0 deleted: 'variable ( traits-array )'
    1799              : 
    1800              :    OpenMP 5.2:
    1801              :    uses_allocators ( [modifier-list :] allocator-list )
    1802              : 
    1803              :    OpenMP 6.0:
    1804              :    uses_allocators ( [modifier-list :] allocator-list [; ...])
    1805              : 
    1806              :    allocator:
    1807              :      variable or predefined-allocator
    1808              :    modifier:
    1809              :      traits ( traits-array )
    1810              :      memspace ( mem-space-handle )  */
    1811              : 
    1812              : static match
    1813           56 : gfc_match_omp_clause_uses_allocators (gfc_omp_clauses *c)
    1814              : {
    1815           60 : parse_next:
    1816           60 :   gfc_symbol *memspace_sym = NULL;
    1817           60 :   gfc_symbol *traits_sym = NULL;
    1818           60 :   gfc_omp_namelist *head = NULL;
    1819           60 :   gfc_omp_namelist *p, *tail, **list;
    1820           60 :   int ntraits, nmemspace;
    1821           60 :   bool has_modifiers;
    1822           60 :   locus old_loc, cur_loc;
    1823              : 
    1824           60 :   gfc_gobble_whitespace ();
    1825           60 :   old_loc = gfc_current_locus;
    1826           60 :   ntraits = nmemspace = 0;
    1827           92 :   do
    1828              :     {
    1829           76 :       cur_loc = gfc_current_locus;
    1830           76 :       if (gfc_match ("traits ( %S ) ", &traits_sym) == MATCH_YES)
    1831           24 :         ntraits++;
    1832           52 :       else if (gfc_match ("memspace ( %S ) ", &memspace_sym) == MATCH_YES)
    1833           23 :         nmemspace++;
    1834           76 :       if (ntraits > 1 || nmemspace > 1)
    1835              :         {
    1836            2 :           gfc_error ("Duplicate %s modifier at %L in USES_ALLOCATORS clause",
    1837              :                      ntraits > 1 ? "TRAITS" : "MEMSPACE", &cur_loc);
    1838            2 :           return MATCH_ERROR;
    1839              :         }
    1840           74 :       if (gfc_match (", ") == MATCH_YES)
    1841           16 :         continue;
    1842           58 :       if (gfc_match (": ") != MATCH_YES)
    1843              :         {
    1844              :           /* Assume no modifier. */
    1845           31 :           memspace_sym = traits_sym = NULL;
    1846           31 :           gfc_current_locus = old_loc;
    1847           31 :           break;
    1848              :         }
    1849              :       break;
    1850              :     } while (true);
    1851              : 
    1852           85 :   has_modifiers = traits_sym != NULL || memspace_sym != NULL;
    1853          150 :   do
    1854              :     {
    1855          104 :       p = gfc_get_omp_namelist ();
    1856          104 :       p->where = gfc_current_locus;
    1857          104 :       if (head == NULL)
    1858              :         head = tail = p;
    1859              :       else
    1860              :         {
    1861           46 :           tail->next = p;
    1862           46 :           tail = tail->next;
    1863              :         }
    1864          104 :       if (gfc_match ("%S ", &p->sym) != MATCH_YES)
    1865            0 :         goto error;
    1866          104 :       if (!has_modifiers)
    1867              :         {
    1868           72 :           if (gfc_match ("( %S ) ", &p->u2.traits_sym) == MATCH_YES)
    1869           17 :             gfc_warning (OPT_Wdeprecated_openmp,
    1870              :                          "The specification of arguments to "
    1871              :                          "%<uses_allocators%> at %L where each item is of "
    1872              :                          "the form %<allocator(traits)%> is deprecated since "
    1873              :                          "OpenMP 5.2; instead use %<uses_allocators(traits(%s"
    1874           17 :                          "): %s)%>", &p->where, p->u2.traits_sym->name,
    1875           17 :                          p->sym->name);
    1876              :         }
    1877           32 :       else if (gfc_peek_ascii_char () == '(')
    1878              :         {
    1879            0 :           gfc_error ("Unexpected %<(%> at %C");
    1880            0 :           goto error;
    1881              :         }
    1882              :       else
    1883              :         {
    1884           32 :           p->u.memspace_sym = memspace_sym;
    1885           32 :           p->u2.traits_sym = traits_sym;
    1886              :         }
    1887          104 :       gfc_gobble_whitespace ();
    1888          104 :       const char c = gfc_peek_ascii_char ();
    1889          104 :       if (c == ';' || c == ')')
    1890              :         break;
    1891           48 :       if (c != ',')
    1892              :         {
    1893            2 :           gfc_error ("Expected %<,%>, %<)%> or %<;%> at %C");
    1894            2 :           goto error;
    1895              :         }
    1896           46 :       gfc_match_char (',');
    1897           46 :       gfc_gobble_whitespace ();
    1898           46 :     } while (true);
    1899              : 
    1900           56 :   list = &c->lists[OMP_LIST_USES_ALLOCATORS];
    1901           74 :   while (*list)
    1902           18 :     list = &(*list)->next;
    1903           56 :   *list = head;
    1904              : 
    1905           56 :   if (gfc_match_char (';') == MATCH_YES)
    1906            4 :     goto parse_next;
    1907              : 
    1908           52 :   gfc_match_char (')');
    1909           52 :   return MATCH_YES;
    1910              : 
    1911            2 : error:
    1912            2 :   gfc_free_omp_namelist (head, false, false, true, false);
    1913            2 :   return MATCH_ERROR;
    1914              : }
    1915              : 
    1916              : 
    1917              : /* Match the 'prefer_type' modifier of the interop 'init' clause:
    1918              :    with either OpenMP 5.1's
    1919              :      prefer_type ( <const-int-expr|string literal> [, ...]
    1920              :    or
    1921              :      prefer_type ( '{' <fr(...) | attr (...)>, ...] '}' [, '{' ... '}' ] )
    1922              :    where 'fr' takes a constant expression or a string literal
    1923              :    and 'attr takes a list of string literals, starting with 'ompx_')
    1924              : 
    1925              :    For the foreign runtime identifiers, string values are converted to
    1926              :    their integer value; unknown string or integer values are set to
    1927              :    GOMP_INTEROP_IFR_KNOWN.
    1928              : 
    1929              :    Data format:
    1930              :     For the foreign runtime identifiers, string values are converted to
    1931              :     their integer value; unknown string or integer values are set to 0.
    1932              : 
    1933              :     Each item (a) GOMP_INTEROP_IFR_SEPARATOR
    1934              :               (b) for any 'fr', its integer value.
    1935              :                   Note: Spec only permits 1 'fr' entry (6.0; changed after TR13)
    1936              :               (c) GOMP_INTEROP_IFR_SEPARATOR
    1937              :               (d) list of \0-terminated non-empty strings for 'attr'
    1938              :               (e) '\0'
    1939              :     Tailing '\0'.  */
    1940              : 
    1941              : static match
    1942           82 : gfc_match_omp_prefer_type (char **type_str, int *type_str_len)
    1943              : {
    1944           82 :   gfc_expr *e;
    1945           82 :   std::string type_string, attr_string;
    1946              :   /* New syntax.  */
    1947           82 :   if (gfc_peek_ascii_char () == '{')
    1948          115 :     do
    1949              :       {
    1950           85 :         attr_string.clear ();
    1951           85 :         type_string += (char) GOMP_INTEROP_IFR_SEPARATOR;
    1952           85 :         if (gfc_match ("{ ") != MATCH_YES)
    1953              :           {
    1954            1 :             gfc_error ("Expected %<{%> at %C");
    1955            1 :             return MATCH_ERROR;
    1956              :           }
    1957              :         bool fr_found = false;
    1958          148 :         do
    1959              :           {
    1960          116 :             if (gfc_match ("fr ( ") == MATCH_YES)
    1961              :               {
    1962           62 :                 if (fr_found)
    1963              :                   {
    1964            1 :                     gfc_error ("Duplicated %<fr%> preference-selector-name "
    1965              :                                "at %C");
    1966            1 :                     return MATCH_ERROR;
    1967              :                   }
    1968           61 :                 fr_found = true;
    1969           61 :                 do
    1970              :                   {
    1971           61 :                     bool found_literal = false;
    1972           61 :                     match m = MATCH_YES;
    1973           61 :                     if (gfc_match_literal_constant (&e, false) == MATCH_YES)
    1974              :                       found_literal = true;
    1975              :                     else
    1976           12 :                       m = gfc_match_expr (&e);
    1977           12 :                     if (m != MATCH_YES
    1978           61 :                         || !gfc_resolve_expr (e)
    1979           61 :                         || e->rank != 0
    1980           60 :                         || e->expr_type != EXPR_CONSTANT
    1981           59 :                         || (e->ts.type != BT_INTEGER
    1982           43 :                             && (!found_literal || e->ts.type != BT_CHARACTER))
    1983           58 :                         || (e->ts.type == BT_INTEGER
    1984           16 :                             && !mpz_fits_sint_p (e->value.integer))
    1985           70 :                         || (e->ts.type == BT_CHARACTER
    1986           42 :                             && (e->ts.kind != gfc_default_character_kind
    1987           41 :                         || e->value.character.length == 0)))
    1988              :                       {
    1989            5 :                         gfc_error ("Expected constant scalar integer expression"
    1990              :                                    " or non-empty default-kind character "
    1991            5 :                                    "literal at %L", &e->where);
    1992            5 :                         gfc_free_expr (e);
    1993            5 :                         return MATCH_ERROR;
    1994              :                       }
    1995           56 :                     gfc_gobble_whitespace ();
    1996           56 :                     int val;
    1997           56 :                     if (e->ts.type == BT_INTEGER)
    1998              :                       {
    1999           16 :                         val = mpz_get_si (e->value.integer);
    2000           16 :                         if (val < 1 || val > GOMP_INTEROP_IFR_LAST)
    2001              :                           {
    2002            0 :                             gfc_warning_now (OPT_Wopenmp,
    2003              :                                              "Unknown foreign runtime "
    2004              :                                              "identifier %qd at %L",
    2005              :                                              val, &e->where);
    2006            0 :                             val = GOMP_INTEROP_IFR_UNKNOWN;
    2007              :                           }
    2008              :                       }
    2009              :                     else
    2010              :                       {
    2011           40 :                         char *str = XALLOCAVEC (char,
    2012              :                                                 e->value.character.length+1);
    2013          229 :                         for (int i = 0; i < e->value.character.length + 1; i++)
    2014          189 :                           str[i] = e->value.character.string[i];
    2015           40 :                         if (memchr (str, '\0', e->value.character.length) != 0)
    2016              :                           {
    2017            0 :                             gfc_error ("Unexpected null character in character "
    2018              :                                        "literal at %L", &e->where);
    2019            0 :                             return MATCH_ERROR;
    2020              :                           }
    2021           40 :                         val = omp_get_fr_id_from_name (str);
    2022           40 :                         if (val == GOMP_INTEROP_IFR_UNKNOWN)
    2023            2 :                           gfc_warning_now (OPT_Wopenmp,
    2024              :                                            "Unknown foreign runtime identifier "
    2025            2 :                                            "%qs at %L", str, &e->where);
    2026              :                       }
    2027              : 
    2028           56 :                     type_string += (char) val;
    2029           56 :                     if (gfc_match (") ") == MATCH_YES)
    2030              :                       break;
    2031            4 :                     gfc_error ("Expected %<)%> at %C");
    2032            4 :                     return MATCH_ERROR;
    2033              :                   }
    2034              :                 while (true);
    2035              :               }
    2036           54 :             else if (gfc_match ("attr ( ") == MATCH_YES)
    2037              :               {
    2038           60 :                 do
    2039              :                   {
    2040           57 :                     if (gfc_match_literal_constant (&e, false) != MATCH_YES
    2041           56 :                         || !gfc_resolve_expr (e)
    2042           56 :                         || e->expr_type != EXPR_CONSTANT
    2043           56 :                         || e->rank != 0
    2044           56 :                         || e->ts.type != BT_CHARACTER
    2045          113 :                         || e->ts.kind != gfc_default_character_kind)
    2046              :                       {
    2047            1 :                         gfc_error ("Expected default-kind character literal "
    2048            1 :                                    "at %L", &e->where);
    2049            1 :                         gfc_free_expr (e);
    2050            1 :                         return MATCH_ERROR;
    2051              :                       }
    2052           56 :                     gfc_gobble_whitespace ();
    2053           56 :                     char *str = XALLOCAVEC (char, e->value.character.length+1);
    2054          564 :                     for (int i = 0; i < e->value.character.length + 1; i++)
    2055          508 :                       str[i] = e->value.character.string[i];
    2056           56 :                     if (!startswith (str, "ompx_"))
    2057              :                       {
    2058            1 :                         gfc_error ("Character literal at %L must start with "
    2059              :                                    "%<ompx_%>", &e->where);
    2060            1 :                         gfc_free_expr (e);
    2061            1 :                         return MATCH_ERROR;
    2062              :                       }
    2063           55 :                     if (memchr (str, '\0', e->value.character.length) != 0
    2064           55 :                         || memchr (str, ',', e->value.character.length) != 0)
    2065              :                       {
    2066            1 :                         gfc_error ("Unexpected null or %<,%> character in "
    2067              :                                    "character literal at %L", &e->where);
    2068            1 :                         return MATCH_ERROR;
    2069              :                       }
    2070           54 :                     attr_string += str;
    2071           54 :                     attr_string += '\0';
    2072           54 :                     if (gfc_match (", ") == MATCH_YES)
    2073            3 :                       continue;
    2074           51 :                     if (gfc_match (") ") == MATCH_YES)
    2075              :                       break;
    2076            0 :                     gfc_error ("Expected %<,%> or %<)%> at %C");
    2077            0 :                     return MATCH_ERROR;
    2078            3 :                   }
    2079              :                 while (true);
    2080              :               }
    2081              :             else
    2082              :               {
    2083            0 :                 gfc_error ("Expected %<fr(%> or %<attr(%> at %C");
    2084            0 :                 return MATCH_ERROR;
    2085              :               }
    2086          103 :             if (gfc_match (", ") == MATCH_YES)
    2087           32 :               continue;
    2088           71 :             if (gfc_match ("} ") == MATCH_YES)
    2089              :               break;
    2090            2 :             gfc_error ("Expected %<,%> or %<}%> at %C");
    2091            2 :             return MATCH_ERROR;
    2092           32 :           }
    2093              :         while (true);
    2094           69 :         type_string += (char) GOMP_INTEROP_IFR_SEPARATOR;
    2095           69 :         type_string += attr_string;
    2096           69 :         type_string += '\0';
    2097           69 :         if (gfc_match (", ") == MATCH_YES)
    2098           30 :           continue;
    2099           39 :         if (gfc_match (") ") == MATCH_YES)
    2100              :           break;
    2101            1 :         gfc_error ("Expected %<,%> or %<)%> at %C");
    2102            1 :         return MATCH_ERROR;
    2103           30 :       }
    2104              :     while (true);
    2105              :   else
    2106           75 :     do
    2107              :       {
    2108           51 :         type_string += (char) GOMP_INTEROP_IFR_SEPARATOR;
    2109           51 :         bool found_literal = false;
    2110           51 :         match m = MATCH_YES;
    2111           51 :         if (gfc_match_literal_constant (&e, false) == MATCH_YES)
    2112              :           found_literal = true;
    2113              :         else
    2114           19 :           m = gfc_match_expr (&e);
    2115           19 :         if (m != MATCH_YES
    2116           51 :             || !gfc_resolve_expr (e)
    2117           51 :             || e->rank != 0
    2118           50 :             || e->expr_type != EXPR_CONSTANT
    2119           49 :             || (e->ts.type != BT_INTEGER
    2120           28 :                 && (!found_literal || e->ts.type != BT_CHARACTER))
    2121           48 :             || (e->ts.type == BT_INTEGER
    2122           21 :                 && !mpz_fits_sint_p (e->value.integer))
    2123           67 :             || (e->ts.type == BT_CHARACTER
    2124           27 :                 && (e->ts.kind != gfc_default_character_kind
    2125           27 :                     || e->value.character.length == 0)))
    2126              :           {
    2127            3 :             gfc_error ("Expected constant scalar integer expression or "
    2128            3 :                        "non-empty default-kind character literal at %L", &e->where);
    2129            3 :             gfc_free_expr (e);
    2130            3 :             return MATCH_ERROR;
    2131              :           }
    2132           48 :         gfc_gobble_whitespace ();
    2133           48 :         int val;
    2134           48 :         if (e->ts.type == BT_INTEGER)
    2135              :           {
    2136           21 :             val = mpz_get_si (e->value.integer);
    2137           21 :             if (val < 1 || val > GOMP_INTEROP_IFR_LAST)
    2138              :               {
    2139            3 :                 gfc_warning_now (OPT_Wopenmp,
    2140              :                                  "Unknown foreign runtime identifier %qd at %L",
    2141              :                                  val, &e->where);
    2142            3 :                 val = 0;
    2143              :               }
    2144              :           }
    2145              :         else
    2146              :           {
    2147           27 :             char *str = XALLOCAVEC (char, e->value.character.length+1);
    2148          169 :             for (int i = 0; i < e->value.character.length + 1; i++)
    2149          142 :               str[i] = e->value.character.string[i];
    2150           27 :             if (memchr (str, '\0', e->value.character.length) != 0)
    2151              :               {
    2152            0 :                 gfc_error ("Unexpected null character in character "
    2153              :                            "literal at %L", &e->where);
    2154            0 :                 return MATCH_ERROR;
    2155              :               }
    2156           27 :             val = omp_get_fr_id_from_name (str);
    2157           27 :             if (val == GOMP_INTEROP_IFR_UNKNOWN)
    2158            5 :               gfc_warning_now (OPT_Wopenmp,
    2159              :                                "Unknown foreign runtime identifier %qs at %L",
    2160            5 :                                str, &e->where);
    2161              :           }
    2162           48 :         type_string += (char) val;
    2163           48 :         type_string += (char) GOMP_INTEROP_IFR_SEPARATOR;
    2164           48 :         type_string += '\0';
    2165           48 :         gfc_free_expr (e);
    2166           48 :         if (gfc_match (", ") == MATCH_YES)
    2167           24 :           continue;
    2168           24 :         if (gfc_match (") ") == MATCH_YES)
    2169              :           break;
    2170            2 :         gfc_error ("Expected %<,%> or %<)%> at %C");
    2171            2 :         return MATCH_ERROR;
    2172           24 :       }
    2173              :     while (true);
    2174           60 :   type_string += '\0';
    2175           60 :   *type_str_len = type_string.length();
    2176           60 :   *type_str = XNEWVEC (char, type_string.length ());
    2177           60 :   memcpy (*type_str, type_string.data (), type_string.length ());
    2178           60 :   return MATCH_YES;
    2179           82 : }
    2180              : 
    2181              : 
    2182              : /* Match OpenMP 5.1's 'init'-clause modifiers, used by the 'init' clause of
    2183              :    the 'interop' directive and the 'append_args' directive of 'declare variant'.
    2184              :      [prefer_type(...)][,][<target|targetsync>, ...])
    2185              : 
    2186              :    If is_init_clause, the modifier parsing ends with a ':'.
    2187              :    If not is_init_clause (i.e. append_args), the parsing ends with ')'.  */
    2188              : 
    2189              : static match
    2190          164 : gfc_parser_omp_clause_init_modifiers (bool &target, bool &targetsync,
    2191              :                                       char **type_str, int &type_str_len,
    2192              :                                       bool is_init_clause)
    2193              : {
    2194          164 :   target = false;
    2195          164 :   targetsync = false;
    2196          164 :   *type_str = NULL;
    2197          164 :   type_str_len = 0;
    2198          286 :   match m;
    2199              : 
    2200          286 :   do
    2201              :     {
    2202          286 :       if (gfc_match ("prefer_type ( ") == MATCH_YES)
    2203              :         {
    2204           83 :           if (*type_str)
    2205              :             {
    2206            1 :               gfc_error ("Duplicate %<prefer_type%> modifier at %C");
    2207            1 :               return MATCH_ERROR;
    2208              :             }
    2209           82 :           m = gfc_match_omp_prefer_type (type_str, &type_str_len);
    2210           82 :           if (m != MATCH_YES)
    2211              :             return m;
    2212           60 :           if (gfc_match (", ") == MATCH_YES)
    2213           14 :             continue;
    2214           46 :           if (is_init_clause)
    2215              :             {
    2216           24 :               if (gfc_match (": ") == MATCH_YES)
    2217              :                 break;
    2218            0 :               gfc_error ("Expected %<,%> or %<:%> at %C");
    2219              :             }
    2220              :           else
    2221              :             {
    2222           22 :               if (gfc_match (") ") == MATCH_YES)
    2223              :                 break;
    2224            0 :               gfc_error ("Expected %<,%> or %<)%> at %C");
    2225              :             }
    2226            0 :           return MATCH_ERROR;
    2227              :         }
    2228              : 
    2229          203 :       if (gfc_match ("prefer_type ") == MATCH_YES)
    2230              :         {
    2231            2 :           gfc_error ("Expected %<(%> after %<prefer_type%> at %C");
    2232            2 :           return MATCH_ERROR;
    2233              :         }
    2234              : 
    2235          201 :       if (gfc_match ("targetsync ") == MATCH_YES)
    2236              :         {
    2237           57 :           if (targetsync)
    2238              :             {
    2239            3 :               gfc_error ("Duplicate %<targetsync%> at %C");
    2240            3 :               return MATCH_ERROR;
    2241              :             }
    2242           54 :           targetsync = true;
    2243           54 :           if (gfc_match (", ") == MATCH_YES)
    2244           13 :             continue;
    2245           41 :           if (!is_init_clause)
    2246              :             {
    2247           23 :               if (gfc_match (") ") == MATCH_YES)
    2248              :                 break;
    2249            0 :               gfc_error ("Expected %<,%> or %<)%> at %C");
    2250            0 :               return MATCH_ERROR;
    2251              :             }
    2252           18 :           if (gfc_match (": ") == MATCH_YES)
    2253              :             break;
    2254            1 :           gfc_error ("Expected %<,%> or %<:%> at %C");
    2255            1 :           return MATCH_ERROR;
    2256              :         }
    2257          144 :       if (gfc_match ("target ") == MATCH_YES)
    2258              :         {
    2259          135 :           if (target)
    2260              :             {
    2261            3 :               gfc_error ("Duplicate %<target%> at %C");
    2262            3 :               return MATCH_ERROR;
    2263              :             }
    2264          132 :           target = true;
    2265          132 :           if (gfc_match (", ") == MATCH_YES)
    2266           95 :             continue;
    2267           37 :           if (!is_init_clause)
    2268              :             {
    2269           11 :               if (gfc_match (") ") == MATCH_YES)
    2270              :                 break;
    2271            0 :               gfc_error ("Expected %<,%> or %<)%> at %C");
    2272            0 :               return MATCH_ERROR;
    2273              :             }
    2274           26 :           if (gfc_match (": ") == MATCH_YES)
    2275              :             break;
    2276            1 :           gfc_error ("Expected %<,%> or %<:%> at %C");
    2277            1 :           return MATCH_ERROR;
    2278              :         }
    2279            9 :       gfc_error ("Expected %<prefer_type%>, %<target%>, or %<targetsync%> "
    2280              :                  "at %C");
    2281            9 :       return MATCH_ERROR;
    2282              :     }
    2283              :   while (true);
    2284              : 
    2285          122 :   if (!target && !targetsync)
    2286              :     {
    2287            4 :       gfc_error ("Missing required %<target%> and/or %<targetsync%> "
    2288              :                  "modifier at %C");
    2289            4 :       return MATCH_ERROR;
    2290              :     }
    2291              :   return MATCH_YES;
    2292              : }
    2293              : 
    2294              : /* Match OpenMP 5.1's 'init' clause for 'interop' objects:
    2295              :    init([prefer_type(...)][,][<target|targetsync>, ...] :] interop-obj-list)  */
    2296              : 
    2297              : static match
    2298          108 : gfc_match_omp_init (gfc_omp_namelist **list)
    2299              : {
    2300          108 :   bool target, targetsync;
    2301          108 :   char *type_str = NULL;
    2302          108 :   int type_str_len;
    2303          108 :   if (gfc_parser_omp_clause_init_modifiers (target, targetsync, &type_str,
    2304              :                                             type_str_len, true) == MATCH_ERROR)
    2305              :     return MATCH_ERROR;
    2306              : 
    2307           64 :   gfc_omp_namelist **head = NULL;
    2308           64 :   if (gfc_match_omp_variable_list ("", list, false, NULL, &head) != MATCH_YES)
    2309              :     return MATCH_ERROR;
    2310          147 :   for (gfc_omp_namelist *n = *head; n; n = n->next)
    2311              :     {
    2312           84 :       n->u.init.target = target;
    2313           84 :       n->u.init.targetsync = targetsync;
    2314           84 :       n->u.init.len = type_str_len;
    2315           84 :       n->u2.init_interop = type_str;
    2316              :     }
    2317              :   return MATCH_YES;
    2318              : }
    2319              : 
    2320              : 
    2321              : /* Match with duplicate check. Matches 'name'. If expr != NULL, it
    2322              :    then matches '(expr)', otherwise, if open_parens is true,
    2323              :    it matches a ' ( ' after 'name'.
    2324              :    dupl_message requires '%qs %L' - and is used by
    2325              :    gfc_match_dupl_memorder and gfc_match_dupl_atomic.  */
    2326              : 
    2327              : static match
    2328        22344 : gfc_match_dupl_check (bool not_dupl, const char *name, bool open_parens = false,
    2329              :                       gfc_expr **expr = NULL, const char *dupl_msg = NULL)
    2330              : {
    2331        22344 :   match m;
    2332        22344 :   char c;
    2333        22344 :   locus old_loc = gfc_current_locus;
    2334        22344 :   if ((m = gfc_match (name)) != MATCH_YES)
    2335              :     return m;
    2336              :   /* Ensure that no partial string is matched.  */
    2337        17391 :   if (gfc_current_form == FORM_FREE
    2338        16893 :       && gfc_match_eos () != MATCH_YES
    2339        30148 :       && ((c = gfc_peek_ascii_char ()) == '_' || ISALNUM (c)))
    2340              :     {
    2341            8 :       gfc_current_locus = old_loc;
    2342            8 :       return MATCH_NO;
    2343              :     }
    2344        17383 :   if (!not_dupl)
    2345              :     {
    2346           44 :       if (dupl_msg)
    2347            2 :         gfc_error (dupl_msg, name, &old_loc);
    2348              :       else
    2349           42 :         gfc_error ("Duplicated %qs clause at %L", name, &old_loc);
    2350           44 :       return MATCH_ERROR;
    2351              :     }
    2352        17339 :   if (open_parens || expr)
    2353              :     {
    2354         9450 :       if (gfc_match (" ( ") != MATCH_YES)
    2355              :         {
    2356           22 :           gfc_error ("Expected %<(%> after %qs at %C", name);
    2357           22 :           return MATCH_ERROR;
    2358              :         }
    2359         9428 :       if (expr)
    2360              :         {
    2361         4406 :           if (gfc_match ("%e )", expr) != MATCH_YES)
    2362              :             {
    2363            9 :               gfc_error ("Invalid expression after %<%s(%> at %C", name);
    2364            9 :               return MATCH_ERROR;
    2365              :             }
    2366              :         }
    2367              :     }
    2368              :   return MATCH_YES;
    2369              : }
    2370              : 
    2371              : static match
    2372          211 : gfc_match_dupl_memorder (bool not_dupl, const char *name)
    2373              : {
    2374            0 :   return gfc_match_dupl_check (not_dupl, name, false, NULL,
    2375              :                                "Duplicated memory-order clause: unexpected %s "
    2376            0 :                                "clause at %L");
    2377              : }
    2378              : 
    2379              : static match
    2380         1175 : gfc_match_dupl_atomic (bool not_dupl, const char *name)
    2381              : {
    2382            0 :   return gfc_match_dupl_check (not_dupl, name, false, NULL,
    2383              :                                "Duplicated atomic clause: unexpected %s "
    2384            0 :                                "clause at %L");
    2385              : }
    2386              : 
    2387              : /* Match OpenMP and OpenACC directive clauses. MASK is a bitmask of
    2388              :    clauses that are allowed for a particular directive.  */
    2389              : 
    2390              : static match
    2391        34081 : gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
    2392              :                        bool first = true, bool needs_space = true,
    2393              :                        bool openacc = false, bool openmp_target = false)
    2394              : {
    2395        34081 :   bool error = false;
    2396        34081 :   gfc_omp_clauses *c = gfc_get_omp_clauses ();
    2397        34081 :   locus old_loc;
    2398              :   /* Determine whether we're dealing with an OpenACC directive that permits
    2399              :      derived type member accesses.  This in particular disallows
    2400              :      "!$acc declare" from using such accesses, because it's not clear if/how
    2401              :      that should work.  */
    2402        34081 :   bool allow_derived = (openacc
    2403        34081 :                         && ((mask & OMP_CLAUSE_ATTACH)
    2404         5927 :                             || (mask & OMP_CLAUSE_DETACH)));
    2405              : 
    2406        34081 :   gcc_checking_assert (OMP_MASK1_LAST <= 64 && OMP_MASK2_LAST <= 64);
    2407        34081 :   *cp = NULL;
    2408       124821 :   while (1)
    2409              :     {
    2410        79451 :       match m = MATCH_NO;
    2411        59130 :       if ((first || (m = gfc_match_char (',')) != MATCH_YES)
    2412       138225 :           && (needs_space && gfc_match_space () != MATCH_YES))
    2413              :         break;
    2414        74904 :       needs_space = false;
    2415        74904 :       first = false;
    2416        74904 :       gfc_gobble_whitespace ();
    2417        74904 :       bool end_colon;
    2418        74904 :       gfc_omp_namelist **head;
    2419        74904 :       old_loc = gfc_current_locus;
    2420        74904 :       char pc = gfc_peek_ascii_char ();
    2421        74904 :       if (pc == '\n' && m == MATCH_YES)
    2422              :         {
    2423            1 :           gfc_error ("Clause expected at %C after trailing comma");
    2424            1 :           goto error;
    2425              :         }
    2426        74903 :       switch (pc)
    2427              :         {
    2428         1310 :         case 'a':
    2429         1310 :           end_colon = false;
    2430         1310 :           head = NULL;
    2431         1334 :           if ((mask & OMP_CLAUSE_ASSUMPTIONS)
    2432         1310 :               && gfc_match ("absent ( ") == MATCH_YES)
    2433              :             {
    2434           27 :               if (gfc_omp_absent_contains_clause (&c->assume, true)
    2435              :                   != MATCH_YES)
    2436            3 :                 goto error;
    2437           24 :               continue;
    2438              :             }
    2439         1283 :           if ((mask & OMP_CLAUSE_ALIGNED)
    2440         1283 :               && gfc_match_omp_variable_list ("aligned (",
    2441              :                                               &c->lists[OMP_LIST_ALIGNED],
    2442              :                                               false, &end_colon,
    2443              :                                               &head) == MATCH_YES)
    2444              :             {
    2445          112 :               gfc_expr *alignment = NULL;
    2446          112 :               gfc_omp_namelist *n;
    2447              : 
    2448          112 :               if (end_colon && gfc_match (" %e )", &alignment) != MATCH_YES)
    2449              :                 {
    2450            0 :                   gfc_free_omp_namelist (*head, false, false, false, false);
    2451            0 :                   gfc_current_locus = old_loc;
    2452            0 :                   *head = NULL;
    2453            0 :                   break;
    2454              :                 }
    2455          268 :               for (n = *head; n; n = n->next)
    2456          156 :                 if (n->next && alignment)
    2457           42 :                   n->expr = gfc_copy_expr (alignment);
    2458              :                 else
    2459          114 :                   n->expr = alignment;
    2460          112 :               continue;
    2461          112 :             }
    2462         1181 :           if ((mask & OMP_CLAUSE_MEMORDER)
    2463         1188 :               && (m = gfc_match_dupl_memorder ((c->memorder
    2464           17 :                                                 == OMP_MEMORDER_UNSET),
    2465              :                                                "acq_rel")) != MATCH_NO)
    2466              :             {
    2467           10 :               if (m == MATCH_ERROR)
    2468            0 :                 goto error;
    2469           10 :               c->memorder = OMP_MEMORDER_ACQ_REL;
    2470           10 :               continue;
    2471              :             }
    2472         1168 :           if ((mask & OMP_CLAUSE_MEMORDER)
    2473         1168 :               && (m = gfc_match_dupl_memorder ((c->memorder
    2474            7 :                                                 == OMP_MEMORDER_UNSET),
    2475              :                                                "acquire")) != MATCH_NO)
    2476              :             {
    2477            7 :               if (m == MATCH_ERROR)
    2478            0 :                 goto error;
    2479            7 :               c->memorder = OMP_MEMORDER_ACQUIRE;
    2480            7 :               continue;
    2481              :             }
    2482         1154 :           if ((mask & OMP_CLAUSE_AFFINITY)
    2483         1154 :               && gfc_match ("affinity ( ") == MATCH_YES)
    2484              :             {
    2485           41 :               gfc_namespace *ns_iter = NULL, *ns_curr = gfc_current_ns;
    2486           41 :               m = gfc_match_iterator (&ns_iter, true);
    2487           41 :               if (m == MATCH_ERROR)
    2488              :                 break;
    2489           31 :               if (m == MATCH_YES && gfc_match (" : ") != MATCH_YES)
    2490              :                 {
    2491            1 :                   gfc_error ("Expected %<:%> at %C");
    2492            1 :                   break;
    2493              :                 }
    2494           30 :               if (ns_iter)
    2495           18 :                 gfc_current_ns = ns_iter;
    2496           30 :               head = NULL;
    2497           30 :               m = gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_AFFINITY],
    2498              :                                                false, NULL, &head, true);
    2499           30 :               gfc_current_ns = ns_curr;
    2500           30 :               if (m == MATCH_ERROR)
    2501              :                 break;
    2502           27 :               if (ns_iter)
    2503              :                 {
    2504           45 :                   for (gfc_omp_namelist *n = *head; n; n = n->next)
    2505              :                     {
    2506           27 :                       n->u2.ns = ns_iter;
    2507           27 :                       ns_iter->refs++;
    2508              :                     }
    2509              :                 }
    2510           27 :               continue;
    2511           27 :             }
    2512         1113 :           if ((mask & OMP_CLAUSE_ALLOCATE)
    2513         1113 :               && gfc_match ("allocate ( ") == MATCH_YES)
    2514              :             {
    2515          279 :               gfc_expr *allocator = NULL;
    2516          279 :               gfc_expr *align = NULL;
    2517          279 :               old_loc = gfc_current_locus;
    2518          279 :               if ((m = gfc_match ("allocator ( %e )", &allocator)) == MATCH_YES)
    2519           50 :                 gfc_match (" , align ( %e )", &align);
    2520          229 :               else if ((m = gfc_match ("align ( %e )", &align)) == MATCH_YES)
    2521           29 :                 gfc_match (" , allocator ( %e )", &allocator);
    2522              : 
    2523          279 :               if (m == MATCH_YES)
    2524              :                 {
    2525           79 :                   if (gfc_match (" : ") != MATCH_YES)
    2526              :                     {
    2527            5 :                       gfc_error ("Expected %<:%> at %C");
    2528            8 :                       goto error;
    2529              :                     }
    2530              :                 }
    2531              :               else
    2532              :                 {
    2533          200 :                   m = gfc_match_expr (&allocator);
    2534          200 :                   if (m == MATCH_YES && gfc_match (" : ") != MATCH_YES)
    2535              :                     {
    2536              :                        /* If no ":" then there is no allocator, we backtrack
    2537              :                           and read the variable list.  */
    2538          101 :                       gfc_free_expr (allocator);
    2539          101 :                       allocator = NULL;
    2540          101 :                       gfc_current_locus = old_loc;
    2541              :                     }
    2542              :                 }
    2543          274 :               gfc_omp_namelist **head = NULL;
    2544          274 :               m = gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_ALLOCATE],
    2545              :                                                true, NULL, &head);
    2546              : 
    2547          274 :               if (m != MATCH_YES)
    2548              :                 {
    2549            3 :                   gfc_free_expr (allocator);
    2550            3 :                   gfc_free_expr (align);
    2551            3 :                   gfc_error ("Expected variable list at %C");
    2552            3 :                   goto error;
    2553              :                 }
    2554              : 
    2555          725 :               for (gfc_omp_namelist *n = *head; n; n = n->next)
    2556              :                 {
    2557          454 :                   n->u2.allocator = allocator;
    2558          454 :                   n->u.align = (align) ? gfc_copy_expr (align) : NULL;
    2559              :                 }
    2560          271 :               gfc_free_expr (align);
    2561          271 :               continue;
    2562          271 :             }
    2563          894 :           if ((mask & OMP_CLAUSE_AT)
    2564          834 :               && (m = gfc_match_dupl_check (c->at == OMP_AT_UNSET, "at", true))
    2565              :                  != MATCH_NO)
    2566              :             {
    2567           66 :               if (m == MATCH_ERROR)
    2568            2 :                 goto error;
    2569           64 :               if (gfc_match ("compilation )") == MATCH_YES)
    2570           15 :                 c->at = OMP_AT_COMPILATION;
    2571           49 :               else if (gfc_match ("execution )") == MATCH_YES)
    2572           45 :                 c->at = OMP_AT_EXECUTION;
    2573              :               else
    2574              :                 {
    2575            4 :                   gfc_error ("Expected COMPILATION or EXECUTION in AT clause "
    2576              :                              "at %C");
    2577            4 :                   goto error;
    2578              :                 }
    2579           60 :               continue;
    2580              :             }
    2581         1411 :           if ((mask & OMP_CLAUSE_ASYNC)
    2582          768 :               && (m = gfc_match_dupl_check (!c->async, "async")) != MATCH_NO)
    2583              :             {
    2584          643 :               if (m == MATCH_ERROR)
    2585            0 :                 goto error;
    2586          643 :               c->async = true;
    2587          643 :               m = gfc_match (" ( %e )", &c->async_expr);
    2588          643 :               if (m == MATCH_ERROR)
    2589              :                 {
    2590            0 :                   gfc_current_locus = old_loc;
    2591            0 :                   break;
    2592              :                 }
    2593          643 :               else if (m == MATCH_NO)
    2594              :                 {
    2595          133 :                   c->async_expr
    2596          133 :                     = gfc_get_constant_expr (BT_INTEGER,
    2597              :                                              gfc_default_integer_kind,
    2598              :                                              &gfc_current_locus);
    2599          133 :                   mpz_set_si (c->async_expr->value.integer, GOMP_ASYNC_NOVAL);
    2600              :                 }
    2601          643 :               continue;
    2602              :             }
    2603          188 :           if ((mask & OMP_CLAUSE_AUTO)
    2604          125 :               && (m = gfc_match_dupl_check (!c->par_auto, "auto"))
    2605              :                  != MATCH_NO)
    2606              :             {
    2607           63 :               if (m == MATCH_ERROR)
    2608            0 :                 goto error;
    2609           63 :               c->par_auto = true;
    2610           63 :               continue;
    2611              :             }
    2612          121 :           if ((mask & OMP_CLAUSE_ATTACH)
    2613           60 :               && gfc_match ("attach ( ") == MATCH_YES
    2614          121 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    2615              :                                            OMP_MAP_ATTACH, false,
    2616              :                                            allow_derived))
    2617           59 :             continue;
    2618              :           break;
    2619           36 :         case 'b':
    2620           70 :           if ((mask & OMP_CLAUSE_BIND)
    2621           36 :               && (m = gfc_match_dupl_check (c->bind == OMP_BIND_UNSET, "bind",
    2622              :                                             true)) != MATCH_NO)
    2623              :             {
    2624           36 :               if (m == MATCH_ERROR)
    2625            1 :                 goto error;
    2626           35 :               if (gfc_match ("teams )") == MATCH_YES)
    2627           11 :                 c->bind = OMP_BIND_TEAMS;
    2628           24 :               else if (gfc_match ("parallel )") == MATCH_YES)
    2629           15 :                 c->bind = OMP_BIND_PARALLEL;
    2630            9 :               else if (gfc_match ("thread )") == MATCH_YES)
    2631            8 :                 c->bind = OMP_BIND_THREAD;
    2632              :               else
    2633              :                 {
    2634            1 :                   gfc_error ("Expected TEAMS, PARALLEL or THREAD as binding in "
    2635              :                              "BIND at %C");
    2636            1 :                   break;
    2637              :                 }
    2638           34 :               continue;
    2639              :             }
    2640              :           break;
    2641         7105 :         case 'c':
    2642         7378 :           if ((mask & OMP_CLAUSE_CAPTURE)
    2643         7105 :               && (m = gfc_match_dupl_check (!c->capture, "capture"))
    2644              :                  != MATCH_NO)
    2645              :             {
    2646          274 :               if (m == MATCH_ERROR)
    2647            1 :                 goto error;
    2648          273 :               c->capture = true;
    2649          273 :               continue;
    2650              :             }
    2651         6831 :           if (mask & OMP_CLAUSE_COLLAPSE)
    2652              :             {
    2653         1995 :               gfc_expr *cexpr = NULL;
    2654         1995 :               if ((m = gfc_match_dupl_check (!c->collapse, "collapse", true,
    2655              :                                              &cexpr)) != MATCH_NO)
    2656              :               {
    2657         1505 :                 int collapse;
    2658         1505 :                 if (m == MATCH_ERROR)
    2659            0 :                   goto error;
    2660         1505 :                 if (gfc_extract_int (cexpr, &collapse, -1))
    2661            4 :                   collapse = 1;
    2662         1501 :                 else if (collapse <= 0)
    2663              :                   {
    2664            8 :                     gfc_error_now ("COLLAPSE clause argument not constant "
    2665              :                                    "positive integer at %C");
    2666            8 :                     collapse = 1;
    2667              :                   }
    2668         1505 :                 gfc_free_expr (cexpr);
    2669         1505 :                 c->collapse = collapse;
    2670         1505 :                 continue;
    2671         1505 :               }
    2672              :             }
    2673         5492 :           if ((mask & OMP_CLAUSE_COMPARE)
    2674         5326 :               && (m = gfc_match_dupl_check (!c->compare, "compare"))
    2675              :                  != MATCH_NO)
    2676              :             {
    2677          167 :               if (m == MATCH_ERROR)
    2678            1 :                 goto error;
    2679          166 :               c->compare = true;
    2680          166 :               continue;
    2681              :             }
    2682         5171 :           if ((mask & OMP_CLAUSE_ASSUMPTIONS)
    2683         5159 :               && gfc_match ("contains ( ") == MATCH_YES)
    2684              :             {
    2685           12 :               if (gfc_omp_absent_contains_clause (&c->assume, false)
    2686              :                   != MATCH_YES)
    2687            0 :                 goto error;
    2688           12 :               continue;
    2689              :             }
    2690         7263 :           if ((mask & OMP_CLAUSE_COPY)
    2691         3720 :               && gfc_match ("copy ( ") == MATCH_YES
    2692         7264 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    2693              :                                            OMP_MAP_TOFROM, true,
    2694              :                                            allow_derived))
    2695         2116 :             continue;
    2696         3031 :           if (mask & OMP_CLAUSE_COPYIN)
    2697              :             {
    2698         2625 :               if (openacc)
    2699              :                 {
    2700         2526 :                   if (gfc_match ("copyin ( ") == MATCH_YES)
    2701              :                     {
    2702         1456 :                       bool readonly = gfc_match ("readonly : ") == MATCH_YES;
    2703         1456 :                       head = NULL;
    2704         1456 :                       if (gfc_match_omp_variable_list ("",
    2705              :                                                        &c->lists[OMP_LIST_MAP],
    2706              :                                                        true, NULL, &head, true,
    2707              :                                                        allow_derived)
    2708              :                           == MATCH_YES)
    2709              :                         {
    2710         1450 :                           gfc_omp_namelist *n;
    2711         3343 :                           for (n = *head; n; n = n->next)
    2712              :                             {
    2713         1893 :                               n->u.map.op = OMP_MAP_TO;
    2714         1893 :                               n->u.map.readonly = readonly;
    2715              :                             }
    2716         1450 :                           continue;
    2717         1450 :                         }
    2718              :                     }
    2719              :                 }
    2720           99 :               else if (gfc_match_omp_variable_list ("copyin (",
    2721              :                                                     &c->lists[OMP_LIST_COPYIN],
    2722              :                                                     true) == MATCH_YES)
    2723           97 :                 continue;
    2724              :             }
    2725         2554 :           if ((mask & OMP_CLAUSE_COPYOUT)
    2726         1215 :               && gfc_match ("copyout ( ") == MATCH_YES
    2727         2554 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    2728              :                                            OMP_MAP_FROM, true, allow_derived))
    2729         1070 :             continue;
    2730          498 :           if ((mask & OMP_CLAUSE_COPYPRIVATE)
    2731          414 :               && gfc_match_omp_variable_list ("copyprivate (",
    2732              :                                               &c->lists[OMP_LIST_COPYPRIVATE],
    2733              :                                               true) == MATCH_YES)
    2734           84 :             continue;
    2735          651 :           if ((mask & OMP_CLAUSE_CREATE)
    2736          328 :               && gfc_match ("create ( ") == MATCH_YES
    2737          651 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    2738              :                                            OMP_MAP_ALLOC, true, allow_derived))
    2739          321 :             continue;
    2740              :           break;
    2741         3722 :         case 'd':
    2742         3722 :           if ((mask & OMP_CLAUSE_DEFAULTMAP)
    2743         3722 :               && gfc_match ("defaultmap ( ") == MATCH_YES)
    2744              :             {
    2745          180 :               enum gfc_omp_defaultmap behavior;
    2746          180 :               gfc_omp_defaultmap_category category
    2747              :                 = OMP_DEFAULTMAP_CAT_UNCATEGORIZED;
    2748          180 :               if (gfc_match ("alloc ") == MATCH_YES)
    2749              :                 behavior = OMP_DEFAULTMAP_ALLOC;
    2750          174 :               else if (gfc_match ("tofrom ") == MATCH_YES)
    2751              :                 behavior = OMP_DEFAULTMAP_TOFROM;
    2752          142 :               else if (gfc_match ("to ") == MATCH_YES)
    2753              :                 behavior = OMP_DEFAULTMAP_TO;
    2754          132 :               else if (gfc_match ("from ") == MATCH_YES)
    2755              :                 behavior = OMP_DEFAULTMAP_FROM;
    2756          129 :               else if (gfc_match ("firstprivate ") == MATCH_YES)
    2757              :                 behavior = OMP_DEFAULTMAP_FIRSTPRIVATE;
    2758           94 :               else if (gfc_match ("present ") == MATCH_YES)
    2759              :                 behavior = OMP_DEFAULTMAP_PRESENT;
    2760           90 :               else if (gfc_match ("none ") == MATCH_YES)
    2761              :                 behavior = OMP_DEFAULTMAP_NONE;
    2762           10 :               else if (gfc_match ("default ") == MATCH_YES)
    2763              :                 behavior = OMP_DEFAULTMAP_DEFAULT;
    2764              :               else
    2765              :                 {
    2766            1 :                   gfc_error ("Expected ALLOC, TO, FROM, TOFROM, FIRSTPRIVATE, "
    2767              :                              "PRESENT, NONE or DEFAULT at %C");
    2768            1 :                   break;
    2769              :                 }
    2770          179 :               if (')' == gfc_peek_ascii_char ())
    2771              :                 ;
    2772          102 :               else if (gfc_match (": ") != MATCH_YES)
    2773              :                 break;
    2774              :               else
    2775              :                 {
    2776          102 :                   if (gfc_match ("scalar ") == MATCH_YES)
    2777              :                     category = OMP_DEFAULTMAP_CAT_SCALAR;
    2778           67 :                   else if (gfc_match ("aggregate ") == MATCH_YES)
    2779              :                     category = OMP_DEFAULTMAP_CAT_AGGREGATE;
    2780           43 :                   else if (gfc_match ("allocatable ") == MATCH_YES)
    2781              :                     category = OMP_DEFAULTMAP_CAT_ALLOCATABLE;
    2782           31 :                   else if (gfc_match ("pointer ") == MATCH_YES)
    2783              :                     category = OMP_DEFAULTMAP_CAT_POINTER;
    2784           14 :                   else if (gfc_match ("all ") == MATCH_YES)
    2785              :                     category = OMP_DEFAULTMAP_CAT_ALL;
    2786              :                   else
    2787              :                     {
    2788            1 :                       gfc_error ("Expected SCALAR, AGGREGATE, ALLOCATABLE, "
    2789              :                                  "POINTER or ALL at %C");
    2790            1 :                       break;
    2791              :                     }
    2792              :                 }
    2793         1193 :               for (int i = 0; i < OMP_DEFAULTMAP_CAT_NUM; ++i)
    2794              :                 {
    2795         1028 :                   if (i != category
    2796         1028 :                       && category != OMP_DEFAULTMAP_CAT_UNCATEGORIZED
    2797          486 :                       && category != OMP_DEFAULTMAP_CAT_ALL
    2798          486 :                       && i != OMP_DEFAULTMAP_CAT_UNCATEGORIZED
    2799          341 :                       && i != OMP_DEFAULTMAP_CAT_ALL)
    2800          254 :                     continue;
    2801          774 :                   if (c->defaultmap[i] != OMP_DEFAULTMAP_UNSET)
    2802              :                     {
    2803           13 :                       const char *pcategory = NULL;
    2804           13 :                       switch (i)
    2805              :                         {
    2806              :                         case OMP_DEFAULTMAP_CAT_UNCATEGORIZED: break;
    2807              :                         case OMP_DEFAULTMAP_CAT_ALL: pcategory = "ALL"; break;
    2808            1 :                         case OMP_DEFAULTMAP_CAT_SCALAR: pcategory = "SCALAR"; break;
    2809            2 :                         case OMP_DEFAULTMAP_CAT_AGGREGATE:
    2810            2 :                           pcategory = "AGGREGATE";
    2811            2 :                           break;
    2812            1 :                         case OMP_DEFAULTMAP_CAT_ALLOCATABLE:
    2813            1 :                           pcategory = "ALLOCATABLE";
    2814            1 :                           break;
    2815            2 :                         case OMP_DEFAULTMAP_CAT_POINTER:
    2816            2 :                           pcategory = "POINTER";
    2817            2 :                           break;
    2818              :                         default: gcc_unreachable ();
    2819              :                         }
    2820            6 :                      if (i == OMP_DEFAULTMAP_CAT_UNCATEGORIZED)
    2821            4 :                       gfc_error ("DEFAULTMAP at %C but prior DEFAULTMAP with "
    2822              :                                  "unspecified category");
    2823              :                      else
    2824            9 :                       gfc_error ("DEFAULTMAP at %C but prior DEFAULTMAP for "
    2825              :                                  "category %s", pcategory);
    2826           13 :                      goto error;
    2827              :                     }
    2828              :                 }
    2829          165 :               c->defaultmap[category] = behavior;
    2830          165 :               if (gfc_match (")") != MATCH_YES)
    2831              :                 break;
    2832          165 :               continue;
    2833          165 :             }
    2834         4497 :           if ((mask & OMP_CLAUSE_DEFAULT)
    2835         3542 :               && (m = gfc_match_dupl_check (c->default_sharing
    2836              :                                             == OMP_DEFAULT_UNKNOWN, "default",
    2837              :                                             true)) != MATCH_NO)
    2838              :             {
    2839         1000 :               if (m == MATCH_ERROR)
    2840            6 :                 goto error;
    2841          994 :               if (gfc_match ("none") == MATCH_YES)
    2842          584 :                 c->default_sharing = OMP_DEFAULT_NONE;
    2843          410 :               else if (openacc)
    2844              :                 {
    2845          225 :                   if (gfc_match ("present") == MATCH_YES)
    2846          195 :                     c->default_sharing = OMP_DEFAULT_PRESENT;
    2847              :                 }
    2848              :               else
    2849              :                 {
    2850          185 :                   if (gfc_match ("firstprivate") == MATCH_YES)
    2851            8 :                     c->default_sharing = OMP_DEFAULT_FIRSTPRIVATE;
    2852          177 :                   else if (gfc_match ("private") == MATCH_YES)
    2853           24 :                     c->default_sharing = OMP_DEFAULT_PRIVATE;
    2854          153 :                   else if (gfc_match ("shared") == MATCH_YES)
    2855          153 :                     c->default_sharing = OMP_DEFAULT_SHARED;
    2856              :                 }
    2857          994 :               if (c->default_sharing == OMP_DEFAULT_UNKNOWN)
    2858              :                 {
    2859           30 :                   if (openacc)
    2860           30 :                     gfc_error ("Expected NONE or PRESENT in DEFAULT clause "
    2861              :                                "at %C");
    2862              :                   else
    2863            0 :                     gfc_error ("Expected NONE, FIRSTPRIVATE, PRIVATE or SHARED "
    2864              :                                "in DEFAULT clause at %C");
    2865           30 :                   goto error;
    2866              :                 }
    2867          964 :               if (gfc_match (" )") != MATCH_YES)
    2868            9 :                 goto error;
    2869          955 :               continue;
    2870              :             }
    2871         2850 :           if ((mask & OMP_CLAUSE_DELETE)
    2872          343 :               && gfc_match ("delete ( ") == MATCH_YES
    2873         2850 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    2874              :                                            OMP_MAP_RELEASE, true,
    2875              :                                            allow_derived))
    2876          308 :             continue;
    2877              :           /* DOACROSS: match 'doacross' and 'depend' with sink/source.
    2878              :              DEPEND: match 'depend' but not sink/source.  */
    2879         2234 :           m = MATCH_NO;
    2880         2234 :           if (((mask & OMP_CLAUSE_DOACROSS)
    2881          383 :                && gfc_match ("doacross ( ") == MATCH_YES)
    2882         2590 :               || (((mask & OMP_CLAUSE_DEPEND) || (mask & OMP_CLAUSE_DOACROSS))
    2883         1595 :                   && (m = gfc_match ("depend ( ")) == MATCH_YES))
    2884              :             {
    2885         1097 :               bool has_omp_all_memory;
    2886         1097 :               bool is_depend = m == MATCH_YES;
    2887         1097 :               gfc_namespace *ns_iter = NULL, *ns_curr = gfc_current_ns;
    2888         1097 :               match m_it = MATCH_NO;
    2889         1097 :               if (is_depend)
    2890         1070 :                 m_it = gfc_match_iterator (&ns_iter, false);
    2891         1070 :               if (m_it == MATCH_ERROR)
    2892              :                 break;
    2893         1092 :               if (m_it == MATCH_YES && gfc_match (" , ") != MATCH_YES)
    2894              :                 break;
    2895         1092 :               m = MATCH_YES;
    2896         1092 :               gfc_omp_depend_doacross_op depend_op = OMP_DEPEND_OUT;
    2897         1092 :               if (gfc_match ("inoutset") == MATCH_YES)
    2898              :                 depend_op = OMP_DEPEND_INOUTSET;
    2899         1080 :               else if (gfc_match ("inout") == MATCH_YES)
    2900              :                 depend_op = OMP_DEPEND_INOUT;
    2901          988 :               else if (gfc_match ("in") == MATCH_YES)
    2902              :                 depend_op = OMP_DEPEND_IN;
    2903          702 :               else if (gfc_match ("out") == MATCH_YES)
    2904              :                 depend_op = OMP_DEPEND_OUT;
    2905          442 :               else if (gfc_match ("mutexinoutset") == MATCH_YES)
    2906              :                 depend_op = OMP_DEPEND_MUTEXINOUTSET;
    2907          424 :               else if (gfc_match ("depobj") == MATCH_YES)
    2908              :                 depend_op = OMP_DEPEND_DEPOBJ;
    2909          387 :               else if (gfc_match ("source") == MATCH_YES)
    2910              :                 {
    2911          143 :                   if (m_it == MATCH_YES)
    2912              :                     {
    2913            1 :                       gfc_error ("ITERATOR may not be combined with SOURCE "
    2914              :                                  "at %C");
    2915           17 :                       goto error;
    2916              :                     }
    2917          142 :                   if (!(mask & OMP_CLAUSE_DOACROSS))
    2918              :                     {
    2919            1 :                       gfc_error ("SOURCE at %C not permitted as dependence-type"
    2920              :                                  " for this directive");
    2921            1 :                       goto error;
    2922              :                     }
    2923          141 :                   if (c->doacross_source)
    2924              :                     {
    2925            0 :                       gfc_error ("Duplicated clause with SOURCE dependence-type"
    2926              :                                  " at %C");
    2927            0 :                       goto error;
    2928              :                     }
    2929          141 :                   gfc_gobble_whitespace ();
    2930          141 :                   m = gfc_match (": ");
    2931          141 :                   if (m != MATCH_YES && !is_depend)
    2932              :                     {
    2933            1 :                       gfc_error ("Expected %<:%> at %C");
    2934            1 :                       goto error;
    2935              :                     }
    2936          140 :                   if (gfc_match (")") != MATCH_YES
    2937          146 :                       && !(m == MATCH_YES
    2938            6 :                            && gfc_match ("omp_cur_iteration )") == MATCH_YES))
    2939              :                     {
    2940            2 :                       gfc_error ("Expected %<)%> or %<omp_cur_iteration)%> "
    2941              :                                  "at %C");
    2942            2 :                       goto error;
    2943              :                     }
    2944          138 :                   if (is_depend)
    2945          130 :                     gfc_warning (OPT_Wdeprecated_openmp,
    2946              :                                  "%<source%> modifier with %<depend%> clause "
    2947              :                                  "at %L deprecated since OpenMP 5.2, use with "
    2948              :                                  "%<doacross%>", &old_loc);
    2949          138 :                   c->doacross_source = true;
    2950          138 :                   c->depend_source = is_depend;
    2951         1075 :                   continue;
    2952              :                 }
    2953          244 :               else if (gfc_match ("sink ") == MATCH_YES)
    2954              :                 {
    2955          244 :                   if (!(mask & OMP_CLAUSE_DOACROSS))
    2956              :                     {
    2957            2 :                       gfc_error ("SINK at %C not permitted as dependence-type "
    2958              :                                  "for this directive");
    2959            2 :                       goto error;
    2960              :                     }
    2961          242 :                   if (gfc_match (": ") != MATCH_YES)
    2962              :                     {
    2963            1 :                       gfc_error ("Expected %<:%> at %C");
    2964            1 :                       goto error;
    2965              :                     }
    2966          241 :                   if (m_it == MATCH_YES)
    2967              :                     {
    2968            0 :                       gfc_error ("ITERATOR may not be combined with SINK "
    2969              :                                  "at %C");
    2970            0 :                       goto error;
    2971              :                     }
    2972          241 :                   if (is_depend)
    2973          226 :                     gfc_warning (OPT_Wdeprecated_openmp,
    2974              :                                  "%<sink%> modifier with %<depend%> clause at "
    2975              :                                  "%L deprecated since OpenMP 5.2, use with "
    2976              :                                  "%<doacross%>", &old_loc);
    2977          241 :                   m = gfc_match_omp_doacross_sink (&c->lists[OMP_LIST_DEPEND],
    2978              :                                                    is_depend);
    2979          241 :                   if (m == MATCH_YES)
    2980          238 :                     continue;
    2981            3 :                   goto error;
    2982              :                 }
    2983              :               else
    2984              :                 m = MATCH_NO;
    2985          705 :               if (!(mask & OMP_CLAUSE_DEPEND))
    2986              :                 {
    2987            0 :                   gfc_error ("Expected dependence-type SINK or SOURCE at %C");
    2988            0 :                   goto error;
    2989              :                 }
    2990          705 :               head = NULL;
    2991          705 :               if (ns_iter)
    2992           37 :                 gfc_current_ns = ns_iter;
    2993          705 :               if (m == MATCH_YES)
    2994          705 :                 m = gfc_match_omp_variable_list (" : ",
    2995              :                                                  &c->lists[OMP_LIST_DEPEND],
    2996              :                                                  false, NULL, &head, true,
    2997              :                                                  false, &has_omp_all_memory);
    2998          705 :               if (m != MATCH_YES)
    2999            2 :                 goto error;
    3000          703 :               gfc_current_ns = ns_curr;
    3001          703 :               if (has_omp_all_memory && depend_op != OMP_DEPEND_INOUT
    3002           21 :                   && depend_op != OMP_DEPEND_OUT)
    3003              :                 {
    3004            4 :                   gfc_error ("%<omp_all_memory%> used with DEPEND kind "
    3005              :                              "other than OUT or INOUT at %C");
    3006            4 :                   goto error;
    3007              :                 }
    3008          699 :               gfc_omp_namelist *n;
    3009         1429 :               for (n = *head; n; n = n->next)
    3010              :                 {
    3011          730 :                   n->u.depend_doacross_op = depend_op;
    3012          730 :                   n->u2.ns = ns_iter;
    3013          730 :                   if (ns_iter)
    3014           36 :                     ns_iter->refs++;
    3015              :                 }
    3016          699 :               continue;
    3017          699 :             }
    3018         1158 :           if ((mask & OMP_CLAUSE_DESTROY)
    3019         1137 :               && gfc_match_omp_variable_list ("destroy (",
    3020              :                                               &c->lists[OMP_LIST_DESTROY],
    3021              :                                               true) == MATCH_YES)
    3022           21 :             continue;
    3023         1242 :           if ((mask & OMP_CLAUSE_DETACH)
    3024          162 :               && !openacc
    3025          127 :               && !c->detach
    3026         1242 :               && gfc_match_omp_detach (&c->detach) == MATCH_YES)
    3027          126 :             continue;
    3028         1025 :           if ((mask & OMP_CLAUSE_DETACH)
    3029           36 :               && openacc
    3030           35 :               && gfc_match ("detach ( ") == MATCH_YES
    3031         1025 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    3032              :                                            OMP_MAP_DETACH, false,
    3033              :                                            allow_derived))
    3034           35 :             continue;
    3035          991 :           if ((mask & OMP_CLAUSE_DEVICEPTR)
    3036           87 :               && gfc_match ("deviceptr ( ") == MATCH_YES
    3037          993 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    3038              :                                            OMP_MAP_FORCE_DEVICEPTR, false,
    3039              :                                            allow_derived))
    3040           36 :             continue;
    3041         1010 :           if ((mask & OMP_CLAUSE_DEVICE_TYPE)
    3042          919 :               && gfc_match_dupl_check (c->device_type == OMP_DEVICE_TYPE_UNSET,
    3043              :                                        "device_type", true) == MATCH_YES)
    3044              :             {
    3045           92 :               if (gfc_match ("host") == MATCH_YES)
    3046           32 :                 c->device_type = OMP_DEVICE_TYPE_HOST;
    3047           60 :               else if (gfc_match ("nohost") == MATCH_YES)
    3048           21 :                 c->device_type = OMP_DEVICE_TYPE_NOHOST;
    3049           39 :               else if (gfc_match ("any") == MATCH_YES)
    3050           38 :                 c->device_type = OMP_DEVICE_TYPE_ANY;
    3051              :               else
    3052              :                 {
    3053            1 :                   gfc_error ("Expected HOST, NOHOST or ANY at %C");
    3054            1 :                   break;
    3055              :                 }
    3056           91 :               if (gfc_match (" )") != MATCH_YES)
    3057              :                 break;
    3058           91 :               continue;
    3059              :             }
    3060          875 :           if ((mask & OMP_CLAUSE_DEVICE_RESIDENT)
    3061          876 :               && gfc_match_omp_variable_list
    3062           49 :                    ("device_resident (",
    3063              :                     &c->lists[OMP_LIST_DEVICE_RESIDENT], true) == MATCH_YES)
    3064           48 :             continue;
    3065         1091 :           if ((mask & OMP_CLAUSE_DEVICE)
    3066          703 :               && openacc
    3067          314 :               && gfc_match ("device ( ") == MATCH_YES
    3068         1092 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    3069              :                                            OMP_MAP_FORCE_TO, true,
    3070              :                                            /* allow_derived = */ true))
    3071          312 :             continue;
    3072          467 :           if ((mask & OMP_CLAUSE_DEVICE)
    3073          391 :               && !openacc
    3074          856 :               && ((m = gfc_match_dupl_check (!c->device, "device", true))
    3075              :                   != MATCH_NO))
    3076              :             {
    3077          349 :               if (m == MATCH_ERROR)
    3078            0 :                 goto error;
    3079          349 :               c->ancestor = false;
    3080          349 :               if (gfc_match ("device_num : ") == MATCH_YES)
    3081              :                 {
    3082           18 :                   if (gfc_match ("%e )", &c->device) != MATCH_YES)
    3083              :                     {
    3084            1 :                       gfc_error ("Expected integer expression at %C");
    3085            1 :                       break;
    3086              :                     }
    3087              :                 }
    3088          331 :               else if (gfc_match ("ancestor : ") == MATCH_YES)
    3089              :                 {
    3090           45 :                   bool has_requires = false;
    3091           45 :                   c->ancestor = true;
    3092           82 :                   for (gfc_namespace *ns = gfc_current_ns; ns; ns = ns->parent)
    3093           80 :                     if (ns->omp_requires & OMP_REQ_REVERSE_OFFLOAD)
    3094              :                       {
    3095              :                         has_requires = true;
    3096              :                         break;
    3097              :                       }
    3098           45 :                   if (!has_requires)
    3099              :                     {
    3100            2 :                       gfc_error ("%<ancestor%> device modifier not "
    3101              :                                  "preceded by %<requires%> directive "
    3102              :                                  "with %<reverse_offload%> clause at %C");
    3103            5 :                       break;
    3104              :                     }
    3105           43 :                   locus old_loc2 = gfc_current_locus;
    3106           43 :                   if (gfc_match ("%e )", &c->device) == MATCH_YES)
    3107              :                     {
    3108           43 :                       int device = 0;
    3109           43 :                       if (!gfc_extract_int (c->device, &device) && device != 1)
    3110              :                       {
    3111            1 :                         gfc_current_locus = old_loc2;
    3112            1 :                         gfc_error ("the %<device%> clause expression must "
    3113              :                                    "evaluate to %<1%> at %C");
    3114            1 :                         break;
    3115              :                       }
    3116              :                     }
    3117              :                   else
    3118              :                     {
    3119            0 :                       gfc_error ("Expected integer expression at %C");
    3120            0 :                       break;
    3121              :                     }
    3122              :                 }
    3123          286 :               else if (gfc_match ("%e )", &c->device) != MATCH_YES)
    3124              :                 {
    3125           13 :                   gfc_error ("Expected integer expression or a single device-"
    3126              :                               "modifier %<device_num%> or %<ancestor%> at %C");
    3127           13 :                   break;
    3128              :                 }
    3129          332 :               continue;
    3130          332 :             }
    3131          118 :           if ((mask & OMP_CLAUSE_DIST_SCHEDULE)
    3132           97 :               && c->dist_sched_kind == OMP_SCHED_NONE
    3133          215 :               && gfc_match ("dist_schedule ( static") == MATCH_YES)
    3134              :             {
    3135           97 :               m = MATCH_NO;
    3136           97 :               c->dist_sched_kind = OMP_SCHED_STATIC;
    3137           97 :               m = gfc_match (" , %e )", &c->dist_chunk_size);
    3138           97 :               if (m != MATCH_YES)
    3139           14 :                 m = gfc_match_char (')');
    3140           14 :               if (m != MATCH_YES)
    3141              :                 {
    3142            0 :                   c->dist_sched_kind = OMP_SCHED_NONE;
    3143            0 :                   gfc_current_locus = old_loc;
    3144              :                 }
    3145              :               else
    3146           97 :                 continue;
    3147              :             }
    3148           32 :           if ((mask & OMP_CLAUSE_DYN_GROUPPRIVATE)
    3149           21 :               && gfc_match_dupl_check (!c->dyn_groupprivate,
    3150              :                                        "dyn_groupprivate", true) == MATCH_YES)
    3151              :             {
    3152           12 :               if (gfc_match ("fallback ( abort ) : ") == MATCH_YES)
    3153            1 :                 c->fallback = OMP_FALLBACK_ABORT;
    3154           11 :               else if (gfc_match ("fallback ( default_mem ) : ") == MATCH_YES)
    3155            1 :                 c->fallback = OMP_FALLBACK_DEFAULT_MEM;
    3156           10 :               else if (gfc_match ("fallback ( null ) : ") == MATCH_YES)
    3157            1 :                 c->fallback = OMP_FALLBACK_NULL;
    3158           12 :               if (gfc_match_expr (&c->dyn_groupprivate) != MATCH_YES)
    3159            0 :                 return MATCH_ERROR;
    3160           12 :               if (gfc_match (" )") != MATCH_YES)
    3161            1 :                 goto error;
    3162           11 :               continue;
    3163              :             }
    3164              :           break;
    3165           90 :         case 'e':
    3166           90 :           if ((mask & OMP_CLAUSE_ENTER))
    3167              :             {
    3168           90 :               m = gfc_match_omp_to_link ("enter (", &c->lists[OMP_LIST_ENTER]);
    3169           90 :               if (m == MATCH_ERROR)
    3170            0 :                 goto error;
    3171           90 :               if (m == MATCH_YES)
    3172           90 :                 continue;
    3173              :             }
    3174              :           break;
    3175         2263 :         case 'f':
    3176         2312 :           if ((mask & OMP_CLAUSE_FAIL)
    3177         2263 :               && (m = gfc_match_dupl_check (c->fail == OMP_MEMORDER_UNSET,
    3178              :                                             "fail", true)) != MATCH_NO)
    3179              :             {
    3180           58 :               if (m == MATCH_ERROR)
    3181            3 :                 goto error;
    3182           55 :               if (gfc_match ("seq_cst") == MATCH_YES)
    3183            6 :                 c->fail = OMP_MEMORDER_SEQ_CST;
    3184           49 :               else if (gfc_match ("acquire") == MATCH_YES)
    3185           14 :                 c->fail = OMP_MEMORDER_ACQUIRE;
    3186           35 :               else if (gfc_match ("relaxed") == MATCH_YES)
    3187           30 :                 c->fail = OMP_MEMORDER_RELAXED;
    3188              :               else
    3189              :                 {
    3190            5 :                   gfc_error ("Expected SEQ_CST, ACQUIRE or RELAXED at %C");
    3191            5 :                   break;
    3192              :                 }
    3193           50 :               if (gfc_match (" )") != MATCH_YES)
    3194            1 :                 goto error;
    3195           49 :               continue;
    3196              :             }
    3197         2248 :           if ((mask & OMP_CLAUSE_FILTER)
    3198         2205 :               && (m = gfc_match_dupl_check (!c->filter, "filter", true,
    3199              :                                             &c->filter)) != MATCH_NO)
    3200              :             {
    3201           44 :               if (m == MATCH_ERROR)
    3202            1 :                 goto error;
    3203           43 :               continue;
    3204              :             }
    3205         2225 :           if ((mask & OMP_CLAUSE_FINAL)
    3206         2161 :               && (m = gfc_match_dupl_check (!c->final_expr, "final", true,
    3207              :                                             &c->final_expr)) != MATCH_NO)
    3208              :             {
    3209           64 :               if (m == MATCH_ERROR)
    3210            0 :                 goto error;
    3211           64 :               continue;
    3212              :             }
    3213         2123 :           if ((mask & OMP_CLAUSE_FINALIZE)
    3214         2097 :               && (m = gfc_match_dupl_check (!c->finalize, "finalize"))
    3215              :                  != MATCH_NO)
    3216              :             {
    3217           26 :               if (m == MATCH_ERROR)
    3218            0 :                 goto error;
    3219           26 :               c->finalize = true;
    3220           26 :               continue;
    3221              :             }
    3222         3066 :           if ((mask & OMP_CLAUSE_FIRSTPRIVATE)
    3223         2071 :               && gfc_match_omp_variable_list ("firstprivate (",
    3224              :                                               &c->lists[OMP_LIST_FIRSTPRIVATE],
    3225              :                                               true) == MATCH_YES)
    3226          995 :             continue;
    3227         2075 :           if ((mask & OMP_CLAUSE_FROM)
    3228         1076 :               && gfc_match_motion_var_list ("from (", &c->lists[OMP_LIST_FROM],
    3229              :                                              &head) == MATCH_YES)
    3230          999 :             continue;
    3231          142 :           if ((mask & OMP_CLAUSE_FULL)
    3232           77 :               && (m = gfc_match_dupl_check (!c->full, "full")) != MATCH_NO)
    3233              :             {
    3234           65 :               if (m == MATCH_ERROR)
    3235            0 :                 goto error;
    3236           65 :               c->full = true;
    3237           65 :               continue;
    3238              :             }
    3239              :           break;
    3240         1230 :         case 'g':
    3241         2421 :           if ((mask & OMP_CLAUSE_GANG)
    3242         1230 :               && (m = gfc_match_dupl_check (!c->gang, "gang")) != MATCH_NO)
    3243              :             {
    3244         1196 :               if (m == MATCH_ERROR)
    3245            0 :                 goto error;
    3246         1196 :               c->gang = true;
    3247         1196 :               m = match_oacc_clause_gwv (c, GOMP_DIM_GANG);
    3248         1196 :               if (m == MATCH_ERROR)
    3249              :                 {
    3250            5 :                   gfc_current_locus = old_loc;
    3251            5 :                   break;
    3252              :                 }
    3253         1191 :               continue;
    3254              :             }
    3255           68 :           if ((mask & OMP_CLAUSE_GRAINSIZE)
    3256           34 :               && (m = gfc_match_dupl_check (!c->grainsize, "grainsize", true))
    3257              :                  != MATCH_NO)
    3258              :             {
    3259           34 :               if (m == MATCH_ERROR)
    3260            0 :                 goto error;
    3261           34 :               if (gfc_match ("strict : ") == MATCH_YES)
    3262            1 :                 c->grainsize_strict = true;
    3263           34 :               if (gfc_match (" %e )", &c->grainsize) != MATCH_YES)
    3264            0 :                 goto error;
    3265           34 :               continue;
    3266              :             }
    3267              :           break;
    3268          465 :         case 'h':
    3269          513 :           if ((mask & OMP_CLAUSE_HAS_DEVICE_ADDR)
    3270          513 :               && gfc_match_omp_variable_list
    3271           48 :                    ("has_device_addr (", &c->lists[OMP_LIST_HAS_DEVICE_ADDR],
    3272              :                     false, NULL, NULL, true) == MATCH_YES)
    3273           48 :             continue;
    3274          460 :           if ((mask & OMP_CLAUSE_HINT)
    3275          417 :               && (m = gfc_match_dupl_check (!c->hint, "hint", true, &c->hint))
    3276              :                  != MATCH_NO)
    3277              :             {
    3278           43 :               if (m == MATCH_ERROR)
    3279            0 :                 goto error;
    3280           43 :               continue;
    3281              :             }
    3282          374 :           if ((mask & OMP_CLAUSE_ASSUMPTIONS)
    3283          374 :               && gfc_match ("holds ( ") == MATCH_YES)
    3284              :             {
    3285           19 :               gfc_expr *e;
    3286           19 :               if (gfc_match ("%e )", &e) != MATCH_YES)
    3287            0 :                 goto error;
    3288           19 :               if (c->assume == NULL)
    3289           12 :                 c->assume = gfc_get_omp_assumptions ();
    3290           19 :               gfc_expr_list *el = XCNEW (gfc_expr_list);
    3291           19 :               el->expr = e;
    3292           19 :               el->next = c->assume->holds;
    3293           19 :               c->assume->holds = el;
    3294           19 :               continue;
    3295           19 :             }
    3296          709 :           if ((mask & OMP_CLAUSE_HOST)
    3297          355 :               && gfc_match ("host ( ") == MATCH_YES
    3298          710 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    3299              :                                            OMP_MAP_FORCE_FROM, true,
    3300              :                                            /* allow_derived = */ true))
    3301          354 :             continue;
    3302              :           break;
    3303         2119 :         case 'i':
    3304         2142 :           if ((mask & OMP_CLAUSE_IF_PRESENT)
    3305         2119 :               && (m = gfc_match_dupl_check (!c->if_present, "if_present"))
    3306              :                  != MATCH_NO)
    3307              :             {
    3308           23 :               if (m == MATCH_ERROR)
    3309            0 :                 goto error;
    3310           23 :               c->if_present = true;
    3311           23 :               continue;
    3312              :             }
    3313         2096 :           if ((mask & OMP_CLAUSE_IF)
    3314         2096 :               && (m = gfc_match_dupl_check (!c->if_expr, "if", true))
    3315              :                  != MATCH_NO)
    3316              :             {
    3317         1347 :               if (m == MATCH_ERROR)
    3318           12 :                 goto error;
    3319         1335 :               if (!openacc)
    3320              :                 {
    3321              :                   /* This should match the enum gfc_omp_if_kind order.  */
    3322              :                   static const char *ifs[OMP_IF_LAST] = {
    3323              :                     "cancel : %e )",
    3324              :                     "parallel : %e )",
    3325              :                     "simd : %e )",
    3326              :                     "task : %e )",
    3327              :                     "taskloop : %e )",
    3328              :                     "target : %e )",
    3329              :                     "target data : %e )",
    3330              :                     "target update : %e )",
    3331              :                     "target enter data : %e )",
    3332              :                     "target exit data : %e )" };
    3333              :                   int i;
    3334         4841 :                   for (i = 0; i < OMP_IF_LAST; i++)
    3335         4443 :                     if (c->if_exprs[i] == NULL
    3336         4443 :                         && gfc_match (ifs[i], &c->if_exprs[i]) == MATCH_YES)
    3337              :                       break;
    3338          536 :                   if (i < OMP_IF_LAST)
    3339          138 :                     continue;
    3340              :                 }
    3341         1197 :               if (gfc_match (" %e )", &c->if_expr) == MATCH_YES)
    3342         1192 :                 continue;
    3343            5 :               goto error;
    3344              :             }
    3345          866 :           if ((mask & OMP_CLAUSE_IN_REDUCTION)
    3346          749 :               && gfc_match_omp_clause_reduction (pc, c, openacc, allow_derived,
    3347              :                                                  openmp_target) == MATCH_YES)
    3348          117 :             continue;
    3349          657 :           if ((mask & OMP_CLAUSE_INBRANCH)
    3350          632 :               && (m = gfc_match_dupl_check (!c->inbranch && !c->notinbranch,
    3351              :                                             "inbranch")) != MATCH_NO)
    3352              :             {
    3353           25 :               if (m == MATCH_ERROR)
    3354            0 :                 goto error;
    3355           25 :               c->inbranch = true;
    3356           25 :               continue;
    3357              :             }
    3358          849 :           if ((mask & OMP_CLAUSE_INDEPENDENT)
    3359          607 :               && (m = gfc_match_dupl_check (!c->independent, "independent"))
    3360              :                  != MATCH_NO)
    3361              :             {
    3362          242 :               if (m == MATCH_ERROR)
    3363            0 :                 goto error;
    3364          242 :               c->independent = true;
    3365          242 :               continue;
    3366              :             }
    3367          365 :           if ((mask & OMP_CLAUSE_INDIRECT)
    3368          365 :               && (m = gfc_match_dupl_check (!c->indirect, "indirect"))
    3369              :                   != MATCH_NO)
    3370              :             {
    3371           61 :               if (m == MATCH_ERROR)
    3372            5 :                 goto error;
    3373           60 :               gfc_expr *indirect_expr = NULL;
    3374           60 :               m = gfc_match (" ( %e )", &indirect_expr);
    3375           60 :               if (m == MATCH_YES)
    3376              :                 {
    3377           13 :                   if (!gfc_resolve_expr (indirect_expr)
    3378           13 :                       || indirect_expr->ts.type != BT_LOGICAL
    3379           23 :                       || indirect_expr->expr_type != EXPR_CONSTANT)
    3380              :                     {
    3381            4 :                       gfc_error ("INDIRECT clause at %C requires a constant "
    3382              :                                  "logical expression");
    3383            4 :                       gfc_free_expr (indirect_expr);
    3384            4 :                       goto error;
    3385              :                     }
    3386            9 :                   c->indirect = indirect_expr->value.logical;
    3387            9 :                   gfc_free_expr (indirect_expr);
    3388              :                 }
    3389              :               else
    3390           47 :                 c->indirect = 1;
    3391           56 :               continue;
    3392           56 :             }
    3393          304 :           if ((mask & OMP_CLAUSE_INIT)
    3394          304 :               && gfc_match ("init ( ") == MATCH_YES)
    3395              :             {
    3396          108 :               m = gfc_match_omp_init (&c->lists[OMP_LIST_INIT]);
    3397          108 :               if (m == MATCH_YES)
    3398           63 :                 continue;
    3399           45 :               goto error;
    3400              :             }
    3401          196 :           if ((mask & OMP_CLAUSE_INTEROP)
    3402          196 :               && (m = gfc_match_dupl_check (!c->lists[OMP_LIST_INTEROP],
    3403              :                                             "interop", true)) != MATCH_NO)
    3404              :             {
    3405              :               /* Note: the interop objects are saved in reverse order to match
    3406              :                  the order in C/C++.  */
    3407          125 :               if (m == MATCH_YES
    3408           63 :                   && (gfc_match_omp_variable_list ("",
    3409              :                                                    &c->lists[OMP_LIST_INTEROP],
    3410              :                                                    false, NULL, NULL, false,
    3411              :                                                    false, NULL, false, true)
    3412              :                       == MATCH_YES))
    3413           62 :                 continue;
    3414            1 :               goto error;
    3415              :             }
    3416          253 :           if ((mask & OMP_CLAUSE_IS_DEVICE_PTR)
    3417          253 :               && gfc_match_omp_variable_list
    3418          120 :                    ("is_device_ptr (",
    3419              :                     &c->lists[OMP_LIST_IS_DEVICE_PTR], false) == MATCH_YES)
    3420          120 :             continue;
    3421              :           break;
    3422         2333 :         case 'l':
    3423         2333 :           if ((mask & OMP_CLAUSE_LASTPRIVATE)
    3424         2333 :               && gfc_match ("lastprivate ( ") == MATCH_YES)
    3425              :             {
    3426         1431 :               bool conditional = gfc_match ("conditional : ") == MATCH_YES;
    3427         1431 :               head = NULL;
    3428         1431 :               if (gfc_match_omp_variable_list ("",
    3429              :                                                &c->lists[OMP_LIST_LASTPRIVATE],
    3430              :                                                false, NULL, &head) == MATCH_YES)
    3431              :                 {
    3432         1431 :                   gfc_omp_namelist *n;
    3433         3737 :                   for (n = *head; n; n = n->next)
    3434         2306 :                     n->u.lastprivate_conditional = conditional;
    3435         1431 :                   continue;
    3436         1431 :                 }
    3437            0 :               gfc_current_locus = old_loc;
    3438            0 :               break;
    3439              :             }
    3440          902 :           end_colon = false;
    3441          902 :           head = NULL;
    3442          902 :           if ((mask & OMP_CLAUSE_LINEAR)
    3443          902 :               && gfc_match ("linear (") == MATCH_YES)
    3444              :             {
    3445          835 :               bool old_linear_modifier = false;
    3446          835 :               gfc_omp_linear_op linear_op = OMP_LINEAR_DEFAULT;
    3447          835 :               gfc_expr *step = NULL;
    3448          835 :               locus saved_loc = gfc_current_locus;
    3449              : 
    3450          835 :               if (gfc_match_omp_variable_list (" ref (",
    3451              :                                                &c->lists[OMP_LIST_LINEAR],
    3452              :                                                false, NULL, &head)
    3453              :                   == MATCH_YES)
    3454              :                 {
    3455              :                   linear_op = OMP_LINEAR_REF;
    3456              :                   old_linear_modifier = true;
    3457              :                 }
    3458          807 :               else if (gfc_match_omp_variable_list (" val (",
    3459              :                                                     &c->lists[OMP_LIST_LINEAR],
    3460              :                                                     false, NULL, &head)
    3461              :                        == MATCH_YES)
    3462              :                 {
    3463              :                   linear_op = OMP_LINEAR_VAL;
    3464              :                   old_linear_modifier = true;
    3465              :                 }
    3466          796 :               else if (gfc_match_omp_variable_list (" uval (",
    3467              :                                                     &c->lists[OMP_LIST_LINEAR],
    3468              :                                                     false, NULL, &head)
    3469              :                        == MATCH_YES)
    3470              :                 {
    3471              :                   linear_op = OMP_LINEAR_UVAL;
    3472              :                   old_linear_modifier = true;
    3473              :                 }
    3474          787 :               else if (gfc_match_omp_variable_list ("",
    3475              :                                                     &c->lists[OMP_LIST_LINEAR],
    3476              :                                                     false, &end_colon, &head)
    3477              :                        == MATCH_YES)
    3478              :                 linear_op = OMP_LINEAR_DEFAULT;
    3479              :               else
    3480              :                 {
    3481            2 :                   gfc_current_locus = old_loc;
    3482            2 :                   break;
    3483              :                 }
    3484              :               if (linear_op != OMP_LINEAR_DEFAULT)
    3485              :                 {
    3486           48 :                   if (gfc_match (" :") == MATCH_YES)
    3487           31 :                     end_colon = true;
    3488           17 :                   else if (gfc_match (" )") != MATCH_YES)
    3489              :                     {
    3490            0 :                       gfc_free_omp_namelist (*head, false, false, false, false);
    3491            0 :                       gfc_current_locus = old_loc;
    3492            0 :                       *head = NULL;
    3493            0 :                       break;
    3494              :                     }
    3495              :                 }
    3496          833 :               gfc_gobble_whitespace ();
    3497          833 :               if (old_linear_modifier && end_colon)
    3498              :                 {
    3499           31 :                   if (gfc_match (" %e )", &step) != MATCH_YES)
    3500              :                     {
    3501            1 :                       gfc_free_omp_namelist (*head, false, false, false, false);
    3502            1 :                       gfc_current_locus = old_loc;
    3503            1 :                       *head = NULL;
    3504            5 :                       goto error;
    3505              :                     }
    3506              :                 }
    3507          832 :               if (old_linear_modifier)
    3508              :                 {
    3509           47 :                   char var_names[512]{};
    3510           47 :                   int count, offset = 0;
    3511          106 :                   for (gfc_omp_namelist *n = *head; n; n = n->next)
    3512              :                     {
    3513           59 :                       if (!n->next)
    3514           47 :                         count = snprintf (var_names + offset,
    3515           47 :                                           sizeof (var_names) - offset,
    3516           47 :                                           "%s", n->sym->name);
    3517              :                       else
    3518           12 :                         count = snprintf (var_names + offset,
    3519           12 :                                           sizeof (var_names) - offset,
    3520           12 :                                           "%s, ", n->sym->name);
    3521           59 :                       if (count < 0 || count >= ((int)sizeof (var_names))
    3522           59 :                                                 - offset)
    3523              :                         {
    3524            0 :                           snprintf (var_names, 512, "%s, ..., ",
    3525            0 :                                     (*head)->sym->name);
    3526            0 :                           while (n->next)
    3527              :                             n = n->next;
    3528            0 :                           offset = strlen (var_names);
    3529            0 :                           snprintf (var_names + offset,
    3530            0 :                                     sizeof (var_names) - offset,
    3531            0 :                                     "%s", n->sym->name);
    3532            0 :                           break;
    3533              :                         }
    3534           59 :                       offset += count;
    3535              :                     }
    3536           47 :                   char *var_names_for_warn = var_names;
    3537           47 :                   const char *op_name;
    3538           47 :                   switch (linear_op)
    3539              :                     {
    3540              :                       case OMP_LINEAR_REF: op_name = "ref"; break;
    3541           10 :                       case OMP_LINEAR_VAL: op_name = "val"; break;
    3542            9 :                       case OMP_LINEAR_UVAL: op_name = "uval"; break;
    3543            0 :                       default: gcc_unreachable ();
    3544              :                     }
    3545           47 :                   gfc_warning (OPT_Wdeprecated_openmp,
    3546              :                                "Specification of the list items as "
    3547              :                                "arguments to the modifiers at %L is "
    3548              :                                "deprecated; since OpenMP 5.2, use "
    3549              :                                "%<linear(%s : %s%s)%>", &saved_loc,
    3550              :                                var_names_for_warn, op_name,
    3551           47 :                                step == nullptr ? "" : ", step(...)");
    3552              :                 }
    3553          785 :               else if (end_colon)
    3554              :                 {
    3555          713 :                   bool has_error = false;
    3556              :                   bool has_modifiers = false;
    3557              :                   bool has_step = false;
    3558          713 :                   bool duplicate_step = false;
    3559          713 :                   bool duplicate_mod = false;
    3560          713 :                   while (true)
    3561              :                     {
    3562          713 :                       old_loc = gfc_current_locus;
    3563          713 :                       bool close_paren = gfc_match ("val )") == MATCH_YES;
    3564          713 :                       if (close_paren || gfc_match ("val , ") == MATCH_YES)
    3565              :                         {
    3566           17 :                           if (linear_op != OMP_LINEAR_DEFAULT)
    3567              :                             {
    3568              :                               duplicate_mod = true;
    3569              :                               break;
    3570              :                             }
    3571           16 :                           linear_op = OMP_LINEAR_VAL;
    3572           16 :                           has_modifiers = true;
    3573           16 :                           if (close_paren)
    3574              :                             break;
    3575           10 :                           continue;
    3576              :                         }
    3577          696 :                       close_paren = gfc_match ("uval )") == MATCH_YES;
    3578          696 :                       if (close_paren || gfc_match ("uval , ") == MATCH_YES)
    3579              :                         {
    3580            7 :                           if (linear_op != OMP_LINEAR_DEFAULT)
    3581              :                             {
    3582              :                               duplicate_mod = true;
    3583              :                               break;
    3584              :                             }
    3585            7 :                           linear_op = OMP_LINEAR_UVAL;
    3586            7 :                           has_modifiers = true;
    3587            7 :                           if (close_paren)
    3588              :                             break;
    3589            2 :                           continue;
    3590              :                         }
    3591          689 :                       close_paren = gfc_match ("ref )") == MATCH_YES;
    3592          689 :                       if (close_paren || gfc_match ("ref , ") == MATCH_YES)
    3593              :                         {
    3594           16 :                           if (linear_op != OMP_LINEAR_DEFAULT)
    3595              :                             {
    3596              :                               duplicate_mod = true;
    3597              :                               break;
    3598              :                             }
    3599           15 :                           linear_op = OMP_LINEAR_REF;
    3600           15 :                           has_modifiers = true;
    3601           15 :                           if (close_paren)
    3602              :                             break;
    3603            7 :                           continue;
    3604              :                         }
    3605          673 :                       close_paren = (gfc_match ("step ( %e ) )", &step)
    3606              :                                      == MATCH_YES);
    3607          684 :                       if (close_paren
    3608          673 :                           || gfc_match ("step ( %e ) , ", &step) == MATCH_YES)
    3609              :                         {
    3610           38 :                           if (has_step)
    3611              :                             {
    3612              :                               duplicate_step = true;
    3613              :                               break;
    3614              :                             }
    3615           37 :                           has_modifiers = has_step = true;
    3616           37 :                           if (close_paren)
    3617              :                             break;
    3618           11 :                           continue;
    3619              :                         }
    3620          635 :                       if (!has_modifiers
    3621          635 :                           && gfc_match ("%e )", &step) == MATCH_YES)
    3622              :                         {
    3623          635 :                           if ((step->expr_type == EXPR_FUNCTION
    3624          634 :                                 || step->expr_type == EXPR_VARIABLE)
    3625           31 :                               && strcmp (step->symtree->name, "step") == 0)
    3626              :                             {
    3627            1 :                               gfc_current_locus = old_loc;
    3628            1 :                               gfc_match ("step (");
    3629            1 :                               has_error = true;
    3630              :                             }
    3631              :                           break;
    3632              :                         }
    3633              :                       has_error = true;
    3634              :                       break;
    3635              :                     }
    3636           49 :                   if (duplicate_mod || duplicate_step)
    3637              :                     {
    3638            3 :                       gfc_error ("Multiple %qs modifiers specified at %C",
    3639              :                                  duplicate_mod ? "linear" : "step");
    3640            3 :                       has_error = true;
    3641              :                     }
    3642          683 :                   if (has_error)
    3643              :                     {
    3644            4 :                       gfc_free_omp_namelist (*head, false, false, false, false);
    3645            4 :                       *head = NULL;
    3646            4 :                       goto error;
    3647              :                     }
    3648              :                 }
    3649          828 :               if (step == NULL)
    3650              :                 {
    3651          129 :                   step = gfc_get_constant_expr (BT_INTEGER,
    3652              :                                                 gfc_default_integer_kind,
    3653              :                                                 &old_loc);
    3654          129 :                   mpz_set_si (step->value.integer, 1);
    3655              :                 }
    3656          828 :               (*head)->expr = step;
    3657          828 :               if (linear_op != OMP_LINEAR_DEFAULT || old_linear_modifier)
    3658          176 :                 for (gfc_omp_namelist *n = *head; n; n = n->next)
    3659              :                   {
    3660           94 :                     n->u.linear.op = linear_op;
    3661           94 :                     n->u.linear.old_modifier = old_linear_modifier;
    3662              :                   }
    3663          828 :               continue;
    3664          828 :             }
    3665           71 :           if ((mask & OMP_CLAUSE_LINK)
    3666           67 :               && openacc
    3667           75 :               && (gfc_match_oacc_clause_link ("link (",
    3668              :                                               &c->lists[OMP_LIST_LINK])
    3669              :                   == MATCH_YES))
    3670            4 :             continue;
    3671          110 :           else if ((mask & OMP_CLAUSE_LINK)
    3672           63 :                    && !openacc
    3673          122 :                    && (gfc_match_omp_to_link ("link (",
    3674              :                                               &c->lists[OMP_LIST_LINK])
    3675              :                        == MATCH_YES))
    3676           47 :             continue;
    3677           28 :           if ((mask & OMP_CLAUSE_LOCAL)
    3678           16 :               && (gfc_match_omp_to_link ("local (", &c->lists[OMP_LIST_LOCAL])
    3679              :                   == MATCH_YES))
    3680           12 :             continue;
    3681              :           break;
    3682         5208 :         case 'm':
    3683         5208 :           if ((mask & OMP_CLAUSE_MAP)
    3684         5208 :               && gfc_match ("map ( ") == MATCH_YES)
    3685              :             {
    3686         5116 :               locus old_loc2 = gfc_current_locus;
    3687         5116 :               int always_modifier = 0;
    3688         5116 :               int close_modifier = 0;
    3689         5116 :               int present_modifier = 0;
    3690         5116 :               locus second_always_locus = old_loc2;
    3691         5116 :               locus second_close_locus = old_loc2;
    3692         5116 :               locus second_present_locus = old_loc2;
    3693              : 
    3694         5640 :               for (;;)
    3695              :                 {
    3696         5378 :                   locus current_locus = gfc_current_locus;
    3697         5378 :                   if (gfc_match ("always ") == MATCH_YES)
    3698              :                     {
    3699          141 :                       if (always_modifier++ == 1)
    3700            5 :                         second_always_locus = current_locus;
    3701              :                     }
    3702         5237 :                   else if (gfc_match ("close ") == MATCH_YES)
    3703              :                     {
    3704           66 :                       if (close_modifier++ == 1)
    3705            5 :                         second_close_locus = current_locus;
    3706              :                     }
    3707         5171 :                   else if (gfc_match ("present ") == MATCH_YES)
    3708              :                     {
    3709           55 :                       if (present_modifier++ == 1)
    3710            4 :                         second_present_locus = current_locus;
    3711              :                     }
    3712              :                   else
    3713              :                     break;
    3714          262 :                   if (gfc_match (", ") != MATCH_YES)
    3715           62 :                     gfc_warning (OPT_Wdeprecated_openmp,
    3716              :                                  "The specification of modifiers without "
    3717              :                                  "comma separators for the %<map%> clause "
    3718              :                                  "at %C has been deprecated since "
    3719              :                                  "OpenMP 5.2");
    3720          262 :                 }
    3721              : 
    3722         5116 :               gfc_omp_map_op map_op = OMP_MAP_TOFROM;
    3723         5116 :               int always_present_modifier
    3724         5116 :                 = always_modifier && present_modifier;
    3725              : 
    3726         5116 :               if (gfc_match ("alloc : ") == MATCH_YES)
    3727          601 :                 map_op = (present_modifier ? OMP_MAP_PRESENT_ALLOC
    3728              :                           : OMP_MAP_ALLOC);
    3729         4515 :               else if (gfc_match ("tofrom : ") == MATCH_YES)
    3730          840 :                 map_op = (always_present_modifier ? OMP_MAP_ALWAYS_PRESENT_TOFROM
    3731          836 :                           : present_modifier ? OMP_MAP_PRESENT_TOFROM
    3732          832 :                           : always_modifier ? OMP_MAP_ALWAYS_TOFROM
    3733              :                           : OMP_MAP_TOFROM);
    3734         3675 :               else if (gfc_match ("to : ") == MATCH_YES)
    3735         1623 :                 map_op = (always_present_modifier ? OMP_MAP_ALWAYS_PRESENT_TO
    3736         1617 :                           : present_modifier ? OMP_MAP_PRESENT_TO
    3737         1606 :                           : always_modifier ? OMP_MAP_ALWAYS_TO
    3738              :                           : OMP_MAP_TO);
    3739         2052 :               else if (gfc_match ("from : ") == MATCH_YES)
    3740         1528 :                 map_op = (always_present_modifier ? OMP_MAP_ALWAYS_PRESENT_FROM
    3741         1524 :                           : present_modifier ? OMP_MAP_PRESENT_FROM
    3742         1520 :                           : always_modifier ? OMP_MAP_ALWAYS_FROM
    3743              :                           : OMP_MAP_FROM);
    3744          524 :               else if (gfc_match ("release : ") == MATCH_YES)
    3745              :                 map_op = OMP_MAP_RELEASE;
    3746          507 :               else if (gfc_match ("delete : ") == MATCH_YES)
    3747              :                 map_op = OMP_MAP_DELETE;
    3748              :               else
    3749              :                 {
    3750          460 :                   gfc_current_locus = old_loc2;
    3751          460 :                   always_modifier = 0;
    3752          460 :                   close_modifier = 0;
    3753              :                 }
    3754              : 
    3755         1264 :               if (always_modifier > 1)
    3756              :                 {
    3757            5 :                   gfc_error ("too many %<always%> modifiers at %L",
    3758              :                              &second_always_locus);
    3759           21 :                   break;
    3760              :                 }
    3761         5111 :               if (close_modifier > 1)
    3762              :                 {
    3763            4 :                   gfc_error ("too many %<close%> modifiers at %L",
    3764              :                              &second_close_locus);
    3765            4 :                   break;
    3766              :                 }
    3767         5107 :               if (present_modifier > 1)
    3768              :                 {
    3769            4 :                   gfc_error ("too many %<present%> modifiers at %L",
    3770              :                              &second_present_locus);
    3771            4 :                   break;
    3772              :                 }
    3773              : 
    3774         5103 :               head = NULL;
    3775         5103 :               if (gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_MAP],
    3776              :                                                false, NULL, &head,
    3777              :                                                true, true) == MATCH_YES)
    3778              :                 {
    3779         5100 :                   gfc_omp_namelist *n;
    3780        11759 :                   for (n = *head; n; n = n->next)
    3781         6659 :                     n->u.map.op = map_op;
    3782         5100 :                   continue;
    3783         5100 :                 }
    3784            3 :               gfc_current_locus = old_loc;
    3785            3 :               break;
    3786              :             }
    3787          126 :           if ((mask & OMP_CLAUSE_MERGEABLE)
    3788           92 :               && (m = gfc_match_dupl_check (!c->mergeable, "mergeable"))
    3789              :                  != MATCH_NO)
    3790              :             {
    3791           34 :               if (m == MATCH_ERROR)
    3792            0 :                 goto error;
    3793           34 :               c->mergeable = true;
    3794           34 :               continue;
    3795              :             }
    3796          111 :           if ((mask & OMP_CLAUSE_MESSAGE)
    3797           58 :               && (m = gfc_match_dupl_check (!c->message, "message", true,
    3798              :                  &c->message)) != MATCH_NO)
    3799              :             {
    3800           58 :               if (m == MATCH_ERROR)
    3801            5 :                 goto error;
    3802           53 :               continue;
    3803              :             }
    3804              :           break;
    3805         2898 :         case 'n':
    3806         2950 :           if ((mask & OMP_CLAUSE_NO_CREATE)
    3807         1343 :               && gfc_match ("no_create ( ") == MATCH_YES
    3808         2950 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    3809              :                                            OMP_MAP_IF_PRESENT, true,
    3810              :                                            allow_derived))
    3811           52 :             continue;
    3812         2847 :           if ((mask & OMP_CLAUSE_ASSUMPTIONS)
    3813         2872 :               && (m = gfc_match_dupl_check (!c->assume
    3814           26 :                                             || !c->assume->no_openmp_constructs,
    3815              :                                             "no_openmp_constructs")) != MATCH_NO)
    3816              :             {
    3817            2 :               if (m == MATCH_ERROR)
    3818            1 :                 goto error;
    3819            1 :               if (c->assume == NULL)
    3820            0 :                 c->assume = gfc_get_omp_assumptions ();
    3821            1 :               c->assume->no_openmp_constructs = true;
    3822            1 :               continue;
    3823              :             }
    3824         2857 :           if ((mask & OMP_CLAUSE_ASSUMPTIONS)
    3825         2868 :               && (m = gfc_match_dupl_check (!c->assume
    3826           24 :                                             || !c->assume->no_openmp_routines,
    3827              :                                             "no_openmp_routines")) != MATCH_NO)
    3828              :             {
    3829           13 :               if (m == MATCH_ERROR)
    3830            0 :                 goto error;
    3831           13 :               if (c->assume == NULL)
    3832           12 :                 c->assume = gfc_get_omp_assumptions ();
    3833           13 :               c->assume->no_openmp_routines = true;
    3834           13 :               continue;
    3835              :             }
    3836         2835 :           if ((mask & OMP_CLAUSE_ASSUMPTIONS)
    3837         2841 :               && (m = gfc_match_dupl_check (!c->assume || !c->assume->no_openmp,
    3838              :                                             "no_openmp")) != MATCH_NO)
    3839              :             {
    3840            4 :               if (m == MATCH_ERROR)
    3841            0 :                 goto error;
    3842            4 :               if (c->assume == NULL)
    3843            4 :                 c->assume = gfc_get_omp_assumptions ();
    3844            4 :               c->assume->no_openmp = true;
    3845            4 :               continue;
    3846              :             }
    3847         2833 :           if ((mask & OMP_CLAUSE_ASSUMPTIONS)
    3848         2834 :               && (m = gfc_match_dupl_check (!c->assume
    3849            7 :                                             || !c->assume->no_parallelism,
    3850              :                                             "no_parallelism")) != MATCH_NO)
    3851              :             {
    3852            6 :               if (m == MATCH_ERROR)
    3853            0 :                 goto error;
    3854            6 :               if (c->assume == NULL)
    3855            6 :                 c->assume = gfc_get_omp_assumptions ();
    3856            6 :               c->assume->no_parallelism = true;
    3857            6 :               continue;
    3858              :             }
    3859              : 
    3860         2831 :           if ((mask & OMP_CLAUSE_NOVARIANTS)
    3861         2821 :               && (m = gfc_match_dupl_check (!c->novariants, "novariants", true,
    3862              :                                             &c->novariants))
    3863              :                    != MATCH_NO)
    3864              :             {
    3865           12 :               if (m == MATCH_ERROR)
    3866            2 :                 goto error;
    3867           10 :               continue;
    3868              :             }
    3869         2822 :           if ((mask & OMP_CLAUSE_NOCONTEXT)
    3870         2809 :               && (m = gfc_match_dupl_check (!c->nocontext, "nocontext", true,
    3871              :                                             &c->nocontext))
    3872              :                    != MATCH_NO)
    3873              :             {
    3874           15 :               if (m == MATCH_ERROR)
    3875            2 :                 goto error;
    3876           13 :               continue;
    3877              :             }
    3878         2808 :           if ((mask & OMP_CLAUSE_NOGROUP)
    3879         2794 :               && (m = gfc_match_dupl_check (!c->nogroup, "nogroup"))
    3880              :                  != MATCH_NO)
    3881              :             {
    3882           14 :               if (m == MATCH_ERROR)
    3883            0 :                 goto error;
    3884           14 :               c->nogroup = true;
    3885           14 :               continue;
    3886              :             }
    3887         2930 :           if ((mask & OMP_CLAUSE_NOHOST)
    3888         2780 :               && (m = gfc_match_dupl_check (!c->nohost, "nohost")) != MATCH_NO)
    3889              :             {
    3890          151 :               if (m == MATCH_ERROR)
    3891            1 :                 goto error;
    3892          150 :               c->nohost = true;
    3893          150 :               continue;
    3894              :             }
    3895         2671 :           if ((mask & OMP_CLAUSE_NOTEMPORAL)
    3896         2629 :               && gfc_match_omp_variable_list ("nontemporal (",
    3897              :                                               &c->lists[OMP_LIST_NONTEMPORAL],
    3898              :                                               true) == MATCH_YES)
    3899           42 :             continue;
    3900         2611 :           if ((mask & OMP_CLAUSE_NOTINBRANCH)
    3901         2588 :               && (m = gfc_match_dupl_check (!c->notinbranch && !c->inbranch,
    3902              :                                             "notinbranch")) != MATCH_NO)
    3903              :             {
    3904           25 :               if (m == MATCH_ERROR)
    3905            1 :                 goto error;
    3906           24 :               c->notinbranch = true;
    3907           24 :               continue;
    3908              :             }
    3909         2691 :           if ((mask & OMP_CLAUSE_NOWAIT)
    3910         2562 :               && (m = gfc_match_dupl_check (!c->nowait, "nowait")) != MATCH_NO)
    3911              :             {
    3912          132 :               if (m == MATCH_ERROR)
    3913            3 :                 goto error;
    3914          129 :               c->nowait = true;
    3915          129 :               continue;
    3916              :             }
    3917         3112 :           if ((mask & OMP_CLAUSE_NUM_GANGS)
    3918         2430 :               && (m = gfc_match_dupl_check (!c->num_gangs_expr, "num_gangs",
    3919              :                                             true)) != MATCH_NO)
    3920              :             {
    3921          686 :               if (m == MATCH_ERROR)
    3922            2 :                 goto error;
    3923          684 :               if (gfc_match (" %e )", &c->num_gangs_expr) != MATCH_YES)
    3924            2 :                 goto error;
    3925          682 :               continue;
    3926              :             }
    3927         1770 :           if ((mask & OMP_CLAUSE_NUM_TASKS)
    3928         1744 :               && (m = gfc_match_dupl_check (!c->num_tasks, "num_tasks", true))
    3929              :                  != MATCH_NO)
    3930              :             {
    3931           26 :               if (m == MATCH_ERROR)
    3932            0 :                 goto error;
    3933           26 :               if (gfc_match ("strict : ") == MATCH_YES)
    3934            1 :                 c->num_tasks_strict = true;
    3935           26 :               if (gfc_match (" %e )", &c->num_tasks) != MATCH_YES)
    3936            0 :                 goto error;
    3937           26 :               continue;
    3938              :             }
    3939         1845 :           if ((mask & OMP_CLAUSE_NUM_TEAMS)
    3940         1718 :               && (m = gfc_match_dupl_check (!c->num_teams_upper, "num_teams",
    3941              :                                             true)) != MATCH_NO)
    3942              :             {
    3943          127 :               if (m == MATCH_ERROR)
    3944            0 :                 goto error;
    3945          127 :               if (gfc_match ("%e ", &c->num_teams_upper) != MATCH_YES)
    3946            0 :                 goto error;
    3947          127 :               if (gfc_peek_ascii_char () == ':')
    3948              :                 {
    3949           21 :                   c->num_teams_lower = c->num_teams_upper;
    3950           21 :                   c->num_teams_upper = NULL;
    3951           21 :                   if (gfc_match (": %e ", &c->num_teams_upper) != MATCH_YES)
    3952            0 :                     goto error;
    3953              :                 }
    3954          127 :               if (gfc_match (") ") != MATCH_YES)
    3955            0 :                 goto error;
    3956          127 :               continue;
    3957              :             }
    3958         2541 :           if ((mask & OMP_CLAUSE_NUM_THREADS)
    3959         1591 :               && (m = gfc_match_dupl_check (!c->num_threads, "num_threads", true,
    3960              :                                             &c->num_threads)) != MATCH_NO)
    3961              :             {
    3962          950 :               if (m == MATCH_ERROR)
    3963            0 :                 goto error;
    3964          950 :               continue;
    3965              :             }
    3966         1240 :           if ((mask & OMP_CLAUSE_NUM_WORKERS)
    3967          641 :               && (m = gfc_match_dupl_check (!c->num_workers_expr, "num_workers",
    3968              :                                             true, &c->num_workers_expr))
    3969              :                  != MATCH_NO)
    3970              :             {
    3971          603 :               if (m == MATCH_ERROR)
    3972            4 :                 goto error;
    3973          599 :               continue;
    3974              :             }
    3975              :           break;
    3976          591 :         case 'o':
    3977          591 :           if ((mask & OMP_CLAUSE_ORDERED)
    3978          591 :               && (m = gfc_match_dupl_check (!c->ordered, "ordered"))
    3979              :                  != MATCH_NO)
    3980              :             {
    3981          343 :               if (m == MATCH_ERROR)
    3982            0 :                 goto error;
    3983          343 :               gfc_expr *cexpr = NULL;
    3984          343 :               m = gfc_match (" ( %e )", &cexpr);
    3985              : 
    3986          343 :               c->ordered = true;
    3987          343 :               if (m == MATCH_YES)
    3988              :                 {
    3989          144 :                   int ordered = 0;
    3990          144 :                   if (gfc_extract_int (cexpr, &ordered, -1))
    3991            0 :                     ordered = 0;
    3992          144 :                   else if (ordered <= 0)
    3993              :                     {
    3994            0 :                       gfc_error_now ("ORDERED clause argument not"
    3995              :                                      " constant positive integer at %C");
    3996            0 :                       ordered = 0;
    3997              :                     }
    3998          144 :                   c->orderedc = ordered;
    3999          144 :                   gfc_free_expr (cexpr);
    4000          144 :                   continue;
    4001          144 :                 }
    4002              : 
    4003          199 :               continue;
    4004          199 :             }
    4005          482 :           if ((mask & OMP_CLAUSE_ORDER)
    4006          248 :               && (m = gfc_match_dupl_check (!c->order_concurrent, "order", true))
    4007              :                  != MATCH_NO)
    4008              :             {
    4009          247 :               if (m == MATCH_ERROR)
    4010           10 :                 goto error;
    4011          237 :               if (gfc_match (" reproducible : concurrent )") == MATCH_YES)
    4012           55 :                 c->order_reproducible = true;
    4013          182 :               else if (gfc_match (" concurrent )") == MATCH_YES)
    4014              :                 ;
    4015           50 :               else if (gfc_match (" unconstrained : concurrent )") == MATCH_YES)
    4016           47 :                 c->order_unconstrained = true;
    4017              :               else
    4018              :                 {
    4019            3 :                   gfc_error ("Expected ORDER(CONCURRENT) at %C "
    4020              :                              "with optional %<reproducible%> or "
    4021              :                              "%<unconstrained%> modifier");
    4022            3 :                   goto error;
    4023              :                 }
    4024          234 :               c->order_concurrent = true;
    4025          234 :               continue;
    4026              :             }
    4027              :           break;
    4028         3093 :         case 'p':
    4029         3093 :           if (mask & OMP_CLAUSE_PARTIAL)
    4030              :             {
    4031          276 :               if ((m = gfc_match_dupl_check (!c->partial, "partial"))
    4032              :                   != MATCH_NO)
    4033              :                 {
    4034          276 :                   int expr;
    4035          276 :                   if (m == MATCH_ERROR)
    4036            0 :                     goto error;
    4037              : 
    4038          276 :                   c->partial = -1;
    4039              : 
    4040          276 :                   gfc_expr *cexpr = NULL;
    4041          276 :                   m = gfc_match (" ( %e )", &cexpr);
    4042          276 :                   if (m == MATCH_NO)
    4043              :                     ;
    4044          251 :                   else if (m == MATCH_YES
    4045          251 :                            && !gfc_extract_int (cexpr, &expr, -1)
    4046          502 :                            && expr > 0)
    4047          247 :                     c->partial = expr;
    4048              :                   else
    4049            4 :                     gfc_error_now ("PARTIAL clause argument not constant "
    4050              :                                    "positive integer at %C");
    4051          276 :                   gfc_free_expr (cexpr);
    4052          276 :                   continue;
    4053          276 :                 }
    4054              :             }
    4055         2886 :           if ((mask & OMP_CLAUSE_COPY)
    4056          877 :               && gfc_match ("pcopy ( ") == MATCH_YES
    4057         2887 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    4058              :                                            OMP_MAP_TOFROM, true, allow_derived))
    4059           69 :             continue;
    4060         2822 :           if ((mask & OMP_CLAUSE_COPYIN)
    4061         1904 :               && gfc_match ("pcopyin ( ") == MATCH_YES
    4062         2822 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    4063              :                                            OMP_MAP_TO, true, allow_derived))
    4064           74 :             continue;
    4065         2747 :           if ((mask & OMP_CLAUSE_COPYOUT)
    4066          735 :               && gfc_match ("pcopyout ( ") == MATCH_YES
    4067         2747 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    4068              :                                            OMP_MAP_FROM, true, allow_derived))
    4069           73 :             continue;
    4070         2616 :           if ((mask & OMP_CLAUSE_CREATE)
    4071          672 :               && gfc_match ("pcreate ( ") == MATCH_YES
    4072         2616 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    4073              :                                            OMP_MAP_ALLOC, true, allow_derived))
    4074           15 :             continue;
    4075         3002 :           if ((mask & OMP_CLAUSE_PRESENT)
    4076          647 :               && gfc_match ("present ( ") == MATCH_YES
    4077         3004 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    4078              :                                            OMP_MAP_FORCE_PRESENT, false,
    4079              :                                            allow_derived))
    4080          416 :             continue;
    4081         2193 :           if ((mask & OMP_CLAUSE_COPY)
    4082          231 :               && gfc_match ("present_or_copy ( ") == MATCH_YES
    4083         2193 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    4084              :                                            OMP_MAP_TOFROM, true,
    4085              :                                            allow_derived))
    4086           23 :             continue;
    4087         2187 :           if ((mask & OMP_CLAUSE_COPYIN)
    4088         1303 :               && gfc_match ("present_or_copyin ( ") == MATCH_YES
    4089         2187 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    4090              :                                            OMP_MAP_TO, true, allow_derived))
    4091           40 :             continue;
    4092         2142 :           if ((mask & OMP_CLAUSE_COPYOUT)
    4093          173 :               && gfc_match ("present_or_copyout ( ") == MATCH_YES
    4094         2142 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    4095              :                                            OMP_MAP_FROM, true, allow_derived))
    4096           35 :             continue;
    4097         2100 :           if ((mask & OMP_CLAUSE_CREATE)
    4098          143 :               && gfc_match ("present_or_create ( ") == MATCH_YES
    4099         2100 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    4100              :                                            OMP_MAP_ALLOC, true, allow_derived))
    4101           28 :             continue;
    4102         2078 :           if ((mask & OMP_CLAUSE_PRIORITY)
    4103         2044 :               && (m = gfc_match_dupl_check (!c->priority, "priority", true,
    4104              :                                             &c->priority)) != MATCH_NO)
    4105              :             {
    4106           34 :               if (m == MATCH_ERROR)
    4107            0 :                 goto error;
    4108           34 :               continue;
    4109              :             }
    4110         3943 :           if ((mask & OMP_CLAUSE_PRIVATE)
    4111         2010 :               && gfc_match_omp_variable_list ("private (",
    4112              :                                               &c->lists[OMP_LIST_PRIVATE],
    4113              :                                               true) == MATCH_YES)
    4114         1933 :             continue;
    4115          141 :           if ((mask & OMP_CLAUSE_PROC_BIND)
    4116          141 :               && (m = gfc_match_dupl_check ((c->proc_bind
    4117           64 :                                              == OMP_PROC_BIND_UNKNOWN),
    4118              :                                             "proc_bind", true)) != MATCH_NO)
    4119              :             {
    4120           64 :               if (m == MATCH_ERROR)
    4121            0 :                 goto error;
    4122           64 :               if (gfc_match ("primary )") == MATCH_YES)
    4123            1 :                 c->proc_bind = OMP_PROC_BIND_PRIMARY;
    4124           63 :               else if (gfc_match ("master )") == MATCH_YES)
    4125              :                 {
    4126            9 :                   gfc_warning (OPT_Wdeprecated_openmp,
    4127              :                                "%<master%> affinity policy at %C deprecated "
    4128              :                                "since OpenMP 5.1, use %<primary%>");
    4129            9 :                   c->proc_bind = OMP_PROC_BIND_MASTER;
    4130              :                 }
    4131           54 :               else if (gfc_match ("spread )") == MATCH_YES)
    4132           53 :                 c->proc_bind = OMP_PROC_BIND_SPREAD;
    4133            1 :               else if (gfc_match ("close )") == MATCH_YES)
    4134            1 :                 c->proc_bind = OMP_PROC_BIND_CLOSE;
    4135              :               else
    4136            0 :                 goto error;
    4137           64 :               continue;
    4138              :             }
    4139              :           break;
    4140         4579 :         case 'r':
    4141         5069 :           if ((mask & OMP_CLAUSE_ATOMIC)
    4142         4579 :               && (m = gfc_match_dupl_atomic ((c->atomic_op
    4143              :                                               == GFC_OMP_ATOMIC_UNSET),
    4144              :                                              "read")) != MATCH_NO)
    4145              :             {
    4146          490 :               if (m == MATCH_ERROR)
    4147            0 :                 goto error;
    4148          490 :               c->atomic_op = GFC_OMP_ATOMIC_READ;
    4149          490 :               continue;
    4150              :             }
    4151         8141 :           if ((mask & OMP_CLAUSE_REDUCTION)
    4152         4089 :               && gfc_match_omp_clause_reduction (pc, c, openacc,
    4153              :                                                  allow_derived) == MATCH_YES)
    4154         4052 :             continue;
    4155           47 :           if ((mask & OMP_CLAUSE_MEMORDER)
    4156           65 :               && (m = gfc_match_dupl_memorder ((c->memorder
    4157           28 :                                                 == OMP_MEMORDER_UNSET),
    4158              :                                                "relaxed")) != MATCH_NO)
    4159              :             {
    4160           10 :               if (m == MATCH_ERROR)
    4161            0 :                 goto error;
    4162           10 :               c->memorder = OMP_MEMORDER_RELAXED;
    4163           10 :               continue;
    4164              :             }
    4165           44 :           if ((mask & OMP_CLAUSE_MEMORDER)
    4166           45 :               && (m = gfc_match_dupl_memorder ((c->memorder
    4167           18 :                                                 == OMP_MEMORDER_UNSET),
    4168              :                                                "release")) != MATCH_NO)
    4169              :             {
    4170           18 :               if (m == MATCH_ERROR)
    4171            1 :                 goto error;
    4172           17 :               c->memorder = OMP_MEMORDER_RELEASE;
    4173           17 :               continue;
    4174              :             }
    4175              :           break;
    4176         3024 :         case 's':
    4177         3117 :           if ((mask & OMP_CLAUSE_SAFELEN)
    4178         3024 :               && (m = gfc_match_dupl_check (!c->safelen_expr, "safelen",
    4179              :                                             true, &c->safelen_expr))
    4180              :                  != MATCH_NO)
    4181              :             {
    4182           93 :               if (m == MATCH_ERROR)
    4183            0 :                 goto error;
    4184           93 :               continue;
    4185              :             }
    4186         2931 :           if ((mask & OMP_CLAUSE_SCHEDULE)
    4187         2931 :               && (m = gfc_match_dupl_check (c->sched_kind == OMP_SCHED_NONE,
    4188              :                                             "schedule", true)) != MATCH_NO)
    4189              :             {
    4190          809 :               if (m == MATCH_ERROR)
    4191            0 :                 goto error;
    4192          809 :               int nmodifiers = 0;
    4193          809 :               locus old_loc2 = gfc_current_locus;
    4194          827 :               do
    4195              :                 {
    4196          818 :                   if (gfc_match ("simd") == MATCH_YES)
    4197              :                     {
    4198           18 :                       c->sched_simd = true;
    4199           18 :                       nmodifiers++;
    4200              :                     }
    4201          800 :                   else if (gfc_match ("monotonic") == MATCH_YES)
    4202              :                     {
    4203           30 :                       c->sched_monotonic = true;
    4204           30 :                       nmodifiers++;
    4205              :                     }
    4206          770 :                   else if (gfc_match ("nonmonotonic") == MATCH_YES)
    4207              :                     {
    4208           35 :                       c->sched_nonmonotonic = true;
    4209           35 :                       nmodifiers++;
    4210              :                     }
    4211              :                   else
    4212              :                     {
    4213          735 :                       if (nmodifiers)
    4214            0 :                         gfc_current_locus = old_loc2;
    4215              :                       break;
    4216              :                     }
    4217           92 :                   if (nmodifiers == 1
    4218           83 :                       && gfc_match (" , ") == MATCH_YES)
    4219            9 :                     continue;
    4220           74 :                   else if (gfc_match (" : ") == MATCH_YES)
    4221              :                     break;
    4222            0 :                   gfc_current_locus = old_loc2;
    4223            0 :                   break;
    4224              :                 }
    4225              :               while (1);
    4226          809 :               if (gfc_match ("static") == MATCH_YES)
    4227          425 :                 c->sched_kind = OMP_SCHED_STATIC;
    4228          384 :               else if (gfc_match ("dynamic") == MATCH_YES)
    4229          164 :                 c->sched_kind = OMP_SCHED_DYNAMIC;
    4230          220 :               else if (gfc_match ("guided") == MATCH_YES)
    4231          127 :                 c->sched_kind = OMP_SCHED_GUIDED;
    4232           93 :               else if (gfc_match ("runtime") == MATCH_YES)
    4233           85 :                 c->sched_kind = OMP_SCHED_RUNTIME;
    4234            8 :               else if (gfc_match ("auto") == MATCH_YES)
    4235            8 :                 c->sched_kind = OMP_SCHED_AUTO;
    4236          809 :               if (c->sched_kind != OMP_SCHED_NONE)
    4237              :                 {
    4238          809 :                   m = MATCH_NO;
    4239          809 :                   if (c->sched_kind != OMP_SCHED_RUNTIME
    4240          809 :                       && c->sched_kind != OMP_SCHED_AUTO)
    4241          716 :                     m = gfc_match (" , %e )", &c->chunk_size);
    4242          716 :                   if (m != MATCH_YES)
    4243          299 :                     m = gfc_match_char (')');
    4244          299 :                   if (m != MATCH_YES)
    4245            0 :                     c->sched_kind = OMP_SCHED_NONE;
    4246              :                 }
    4247          809 :               if (c->sched_kind != OMP_SCHED_NONE)
    4248          809 :                 continue;
    4249              :               else
    4250            0 :                 gfc_current_locus = old_loc;
    4251              :             }
    4252         2305 :           if ((mask & OMP_CLAUSE_SELF)
    4253          335 :               && !(mask & OMP_CLAUSE_HOST) /* OpenACC compute construct */
    4254         2362 :               && (m = gfc_match_dupl_check (!c->self_expr, "self"))
    4255              :                   != MATCH_NO)
    4256              :             {
    4257          186 :               if (m == MATCH_ERROR)
    4258            3 :                 goto error;
    4259          183 :               m = gfc_match (" ( %e )", &c->self_expr);
    4260          183 :               if (m == MATCH_ERROR)
    4261              :                 {
    4262            0 :                   gfc_current_locus = old_loc;
    4263            0 :                   break;
    4264              :                 }
    4265          183 :               else if (m == MATCH_NO)
    4266            9 :                 c->self_expr = gfc_get_logical_expr (gfc_default_logical_kind,
    4267              :                                                      NULL, true);
    4268          183 :               continue;
    4269              :             }
    4270         2030 :           if ((mask & OMP_CLAUSE_SELF)
    4271          149 :               && (mask & OMP_CLAUSE_HOST) /* OpenACC 'update' directive */
    4272           95 :               && gfc_match ("self ( ") == MATCH_YES
    4273         2031 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    4274              :                                            OMP_MAP_FORCE_FROM, true,
    4275              :                                            /* allow_derived = */ true))
    4276           94 :             continue;
    4277         2190 :           if ((mask & OMP_CLAUSE_SEQ)
    4278         1842 :               && (m = gfc_match_dupl_check (!c->seq, "seq")) != MATCH_NO)
    4279              :             {
    4280          348 :               if (m == MATCH_ERROR)
    4281            0 :                 goto error;
    4282          348 :               c->seq = true;
    4283          348 :               continue;
    4284              :             }
    4285         1635 :           if ((mask & OMP_CLAUSE_MEMORDER)
    4286         1635 :               && (m = gfc_match_dupl_memorder ((c->memorder
    4287          141 :                                                 == OMP_MEMORDER_UNSET),
    4288              :                                                "seq_cst")) != MATCH_NO)
    4289              :             {
    4290          141 :               if (m == MATCH_ERROR)
    4291            0 :                 goto error;
    4292          141 :               c->memorder = OMP_MEMORDER_SEQ_CST;
    4293          141 :               continue;
    4294              :             }
    4295         2316 :           if ((mask & OMP_CLAUSE_SHARED)
    4296         1353 :               && gfc_match_omp_variable_list ("shared (",
    4297              :                                               &c->lists[OMP_LIST_SHARED],
    4298              :                                               true) == MATCH_YES)
    4299          963 :             continue;
    4300          508 :           if ((mask & OMP_CLAUSE_SIMDLEN)
    4301          390 :               && (m = gfc_match_dupl_check (!c->simdlen_expr, "simdlen", true,
    4302              :                                             &c->simdlen_expr)) != MATCH_NO)
    4303              :             {
    4304          118 :               if (m == MATCH_ERROR)
    4305            0 :                 goto error;
    4306          118 :               continue;
    4307              :             }
    4308          294 :           if ((mask & OMP_CLAUSE_SIMD)
    4309          272 :               && (m = gfc_match_dupl_check (!c->simd, "simd")) != MATCH_NO)
    4310              :             {
    4311           22 :               if (m == MATCH_ERROR)
    4312            0 :                 goto error;
    4313           22 :               c->simd = true;
    4314           22 :               continue;
    4315              :             }
    4316          289 :           if ((mask & OMP_CLAUSE_SEVERITY)
    4317          250 :               && (m = gfc_match_dupl_check (!c->severity, "severity", true))
    4318              :                  != MATCH_NO)
    4319              :             {
    4320           45 :               if (m == MATCH_ERROR)
    4321            2 :                 goto error;
    4322           43 :               if (gfc_match ("fatal )") == MATCH_YES)
    4323           10 :                 c->severity = OMP_SEVERITY_FATAL;
    4324           33 :               else if (gfc_match ("warning )") == MATCH_YES)
    4325           29 :                 c->severity = OMP_SEVERITY_WARNING;
    4326              :               else
    4327              :                 {
    4328            4 :                   gfc_error ("Expected FATAL or WARNING in SEVERITY clause "
    4329              :                              "at %C");
    4330            4 :                   goto error;
    4331              :                 }
    4332           39 :               continue;
    4333              :             }
    4334          205 :           if ((mask & OMP_CLAUSE_SIZES)
    4335          205 :               && ((m = gfc_match_dupl_check (!c->sizes_list, "sizes"))
    4336              :                   != MATCH_NO))
    4337              :             {
    4338          203 :               if (m == MATCH_ERROR)
    4339            0 :                 goto error;
    4340          203 :               m = match_omp_oacc_expr_list (" (", &c->sizes_list, false, true);
    4341          203 :               if (m == MATCH_ERROR)
    4342            7 :                 goto error;
    4343          196 :               if (m == MATCH_YES)
    4344          195 :                 continue;
    4345            1 :               gfc_error ("Expected %<(%> after %qs at %C", "sizes");
    4346            1 :               goto error;
    4347              :             }
    4348              :           break;
    4349         1203 :         case 't':
    4350         1268 :           if ((mask & OMP_CLAUSE_TASK_REDUCTION)
    4351         1203 :               && gfc_match_omp_clause_reduction (pc, c, openacc,
    4352              :                                                  allow_derived) == MATCH_YES)
    4353           65 :             continue;
    4354         1210 :           if ((mask & OMP_CLAUSE_THREAD_LIMIT)
    4355         1138 :               && (m = gfc_match_dupl_check (!c->thread_limit, "thread_limit",
    4356              :                                             true, &c->thread_limit))
    4357              :                  != MATCH_NO)
    4358              :             {
    4359           72 :               if (m == MATCH_ERROR)
    4360            0 :                 goto error;
    4361           72 :               continue;
    4362              :             }
    4363         1079 :           if ((mask & OMP_CLAUSE_THREADS)
    4364         1066 :               && (m = gfc_match_dupl_check (!c->threads, "threads"))
    4365              :                  != MATCH_NO)
    4366              :             {
    4367           13 :               if (m == MATCH_ERROR)
    4368            0 :                 goto error;
    4369           13 :               c->threads = true;
    4370           13 :               continue;
    4371              :             }
    4372         1250 :           if ((mask & OMP_CLAUSE_TILE)
    4373          221 :               && !c->tile_list
    4374         1274 :               && match_omp_oacc_expr_list ("tile (", &c->tile_list,
    4375              :                                            true, false) == MATCH_YES)
    4376          197 :             continue;
    4377          856 :           if ((mask & OMP_CLAUSE_TO) && (mask & OMP_CLAUSE_LINK))
    4378              :             {
    4379              :               /* Declare target: 'to' is an alias for 'enter';
    4380              :                  'to' is deprecated since 5.2.  */
    4381          116 :               m = gfc_match_omp_to_link ("to (", &c->lists[OMP_LIST_TO]);
    4382          116 :               if (m == MATCH_ERROR)
    4383            0 :                 goto error;
    4384          116 :               if (m == MATCH_YES)
    4385              :                 {
    4386          116 :                   gfc_warning (OPT_Wdeprecated_openmp,
    4387              :                                "%<to%> clause with %<declare target%> at %L "
    4388              :                                "deprecated since OpenMP 5.2, use %<enter%>",
    4389              :                                &old_loc);
    4390          116 :                   continue;
    4391              :                 }
    4392              :             }
    4393         1456 :           else if ((mask & OMP_CLAUSE_TO)
    4394          740 :                    && gfc_match_motion_var_list ("to (", &c->lists[OMP_LIST_TO],
    4395              :                                                  &head) == MATCH_YES)
    4396          716 :             continue;
    4397              :           break;
    4398         1516 :         case 'u':
    4399         1574 :           if ((mask & OMP_CLAUSE_UNIFORM)
    4400         1516 :               && gfc_match_omp_variable_list ("uniform (",
    4401              :                                               &c->lists[OMP_LIST_UNIFORM],
    4402              :                                               false) == MATCH_YES)
    4403           58 :             continue;
    4404         1599 :           if ((mask & OMP_CLAUSE_UNTIED)
    4405         1458 :               && (m = gfc_match_dupl_check (!c->untied, "untied")) != MATCH_NO)
    4406              :             {
    4407          141 :               if (m == MATCH_ERROR)
    4408            0 :                 goto error;
    4409          141 :               c->untied = true;
    4410          141 :               continue;
    4411              :             }
    4412         1561 :           if ((mask & OMP_CLAUSE_ATOMIC)
    4413         1317 :               && (m = gfc_match_dupl_atomic ((c->atomic_op
    4414              :                                               == GFC_OMP_ATOMIC_UNSET),
    4415              :                                              "update")) != MATCH_NO)
    4416              :             {
    4417          245 :               if (m == MATCH_ERROR)
    4418            1 :                 goto error;
    4419          244 :               c->atomic_op = GFC_OMP_ATOMIC_UPDATE;
    4420          244 :               continue;
    4421              :             }
    4422         1094 :           if ((mask & OMP_CLAUSE_USE)
    4423         1072 :               && gfc_match_omp_variable_list ("use (",
    4424              :                                               &c->lists[OMP_LIST_USE],
    4425              :                                               true) == MATCH_YES)
    4426           22 :             continue;
    4427         1110 :           if ((mask & OMP_CLAUSE_USE_DEVICE)
    4428         1050 :               && gfc_match_omp_variable_list ("use_device (",
    4429              :                                               &c->lists[OMP_LIST_USE_DEVICE],
    4430              :                                               true) == MATCH_YES)
    4431           60 :             continue;
    4432         1153 :           if ((mask & OMP_CLAUSE_USE_DEVICE_PTR)
    4433         1918 :               && gfc_match_omp_variable_list
    4434          928 :                    ("use_device_ptr (",
    4435              :                     &c->lists[OMP_LIST_USE_DEVICE_PTR], false) == MATCH_YES)
    4436          163 :             continue;
    4437         1592 :           if ((mask & OMP_CLAUSE_USE_DEVICE_ADDR)
    4438         1592 :               && gfc_match_omp_variable_list
    4439          765 :                    ("use_device_addr (", &c->lists[OMP_LIST_USE_DEVICE_ADDR],
    4440              :                     false, NULL, NULL, true) == MATCH_YES)
    4441          765 :             continue;
    4442          114 :           if ((mask & OMP_CLAUSE_USES_ALLOCATORS)
    4443           62 :               && (gfc_match ("uses_allocators ( ") == MATCH_YES))
    4444              :             {
    4445           56 :               if (gfc_match_omp_clause_uses_allocators (c) != MATCH_YES)
    4446            4 :                 goto error;
    4447           52 :               continue;
    4448              :             }
    4449              :           break;
    4450         1570 :         case 'v':
    4451              :           /* VECTOR_LENGTH must be matched before VECTOR, because the latter
    4452              :              doesn't unconditionally match '('.  */
    4453         2139 :           if ((mask & OMP_CLAUSE_VECTOR_LENGTH)
    4454         1570 :               && (m = gfc_match_dupl_check (!c->vector_length_expr,
    4455              :                                             "vector_length", true,
    4456              :                                             &c->vector_length_expr))
    4457              :                  != MATCH_NO)
    4458              :             {
    4459          573 :               if (m == MATCH_ERROR)
    4460            4 :                 goto error;
    4461          569 :               continue;
    4462              :             }
    4463         1989 :           if ((mask & OMP_CLAUSE_VECTOR)
    4464          997 :               && (m = gfc_match_dupl_check (!c->vector, "vector")) != MATCH_NO)
    4465              :             {
    4466          995 :               if (m == MATCH_ERROR)
    4467            0 :                 goto error;
    4468          995 :               c->vector = true;
    4469          995 :               m = match_oacc_clause_gwv (c, GOMP_DIM_VECTOR);
    4470          995 :               if (m == MATCH_ERROR)
    4471            3 :                 goto error;
    4472          992 :               continue;
    4473              :             }
    4474              :           break;
    4475         1482 :         case 'w':
    4476         1482 :           if ((mask & OMP_CLAUSE_WAIT)
    4477         1482 :               && gfc_match ("wait") == MATCH_YES)
    4478              :             {
    4479          192 :               m = match_omp_oacc_expr_list (" (", &c->wait_list, false, false);
    4480          192 :               if (m == MATCH_ERROR)
    4481            9 :                 goto error;
    4482          183 :               else if (m == MATCH_NO)
    4483              :                 {
    4484           47 :                   gfc_expr *expr
    4485           47 :                     = gfc_get_constant_expr (BT_INTEGER,
    4486              :                                              gfc_default_integer_kind,
    4487              :                                              &gfc_current_locus);
    4488           47 :                   mpz_set_si (expr->value.integer, GOMP_ASYNC_NOVAL);
    4489           47 :                   gfc_expr_list **expr_list = &c->wait_list;
    4490           56 :                   while (*expr_list)
    4491            9 :                     expr_list = &(*expr_list)->next;
    4492           47 :                   *expr_list = gfc_get_expr_list ();
    4493           47 :                   (*expr_list)->expr = expr;
    4494           47 :                   needs_space = true;
    4495              :                 }
    4496          183 :               continue;
    4497          183 :             }
    4498         1303 :           if ((mask & OMP_CLAUSE_WEAK)
    4499         1290 :               && (m = gfc_match_dupl_check (!c->weak, "weak"))
    4500              :                  != MATCH_NO)
    4501              :             {
    4502           14 :               if (m == MATCH_ERROR)
    4503            1 :                 goto error;
    4504           13 :               c->weak = true;
    4505           13 :               continue;
    4506              :             }
    4507         2137 :           if ((mask & OMP_CLAUSE_WORKER)
    4508         1276 :               && (m = gfc_match_dupl_check (!c->worker, "worker")) != MATCH_NO)
    4509              :             {
    4510          864 :               if (m == MATCH_ERROR)
    4511            0 :                 goto error;
    4512          864 :               c->worker = true;
    4513          864 :               m = match_oacc_clause_gwv (c, GOMP_DIM_WORKER);
    4514          864 :               if (m == MATCH_ERROR)
    4515            3 :                 goto error;
    4516          861 :               continue;
    4517              :             }
    4518          824 :           if ((mask & OMP_CLAUSE_ATOMIC)
    4519          412 :               && (m = gfc_match_dupl_atomic ((c->atomic_op
    4520              :                                               == GFC_OMP_ATOMIC_UNSET),
    4521              :                                              "write")) != MATCH_NO)
    4522              :             {
    4523          412 :               if (m == MATCH_ERROR)
    4524            0 :                 goto error;
    4525          412 :               c->atomic_op = GFC_OMP_ATOMIC_WRITE;
    4526          412 :               continue;
    4527              :             }
    4528              :           break;
    4529              :         }
    4530              :       break;
    4531        45370 :     }
    4532              : 
    4533        34081 : end:
    4534        33827 :   if (error || gfc_match_omp_eos () != MATCH_YES)
    4535              :     {
    4536          521 :       if (!gfc_error_flag_test ())
    4537          137 :         gfc_error ("Failed to match clause at %C");
    4538          521 :       gfc_free_omp_clauses (c);
    4539          521 :       return MATCH_ERROR;
    4540              :     }
    4541              : 
    4542        33560 :   *cp = c;
    4543        33560 :   return MATCH_YES;
    4544              : 
    4545          254 : error:
    4546          254 :   error = true;
    4547          254 :   goto end;
    4548              : }
    4549              : 
    4550              : 
    4551              : #define OACC_PARALLEL_CLAUSES \
    4552              :   (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_NUM_GANGS         \
    4553              :    | OMP_CLAUSE_NUM_WORKERS | OMP_CLAUSE_VECTOR_LENGTH | OMP_CLAUSE_REDUCTION \
    4554              :    | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT                 \
    4555              :    | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT            \
    4556              :    | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE      \
    4557              :    | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH                 \
    4558              :    | OMP_CLAUSE_SELF)
    4559              : #define OACC_KERNELS_CLAUSES \
    4560              :   (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_NUM_GANGS         \
    4561              :    | OMP_CLAUSE_NUM_WORKERS | OMP_CLAUSE_VECTOR_LENGTH | OMP_CLAUSE_DEVICEPTR \
    4562              :    | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT                 \
    4563              :    | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT            \
    4564              :    | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH                 \
    4565              :    | OMP_CLAUSE_SELF)
    4566              : #define OACC_SERIAL_CLAUSES \
    4567              :   (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_REDUCTION         \
    4568              :    | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT                 \
    4569              :    | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT            \
    4570              :    | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE      \
    4571              :    | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH                 \
    4572              :    | OMP_CLAUSE_SELF)
    4573              : #define OACC_DATA_CLAUSES \
    4574              :   (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_DEVICEPTR  | OMP_CLAUSE_COPY         \
    4575              :    | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_CREATE               \
    4576              :    | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT | OMP_CLAUSE_ATTACH            \
    4577              :    | OMP_CLAUSE_DEFAULT)
    4578              : #define OACC_LOOP_CLAUSES \
    4579              :   (omp_mask (OMP_CLAUSE_COLLAPSE) | OMP_CLAUSE_GANG | OMP_CLAUSE_WORKER       \
    4580              :    | OMP_CLAUSE_VECTOR | OMP_CLAUSE_SEQ | OMP_CLAUSE_INDEPENDENT              \
    4581              :    | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_AUTO              \
    4582              :    | OMP_CLAUSE_TILE)
    4583              : #define OACC_PARALLEL_LOOP_CLAUSES \
    4584              :   (OACC_LOOP_CLAUSES | OACC_PARALLEL_CLAUSES)
    4585              : #define OACC_KERNELS_LOOP_CLAUSES \
    4586              :   (OACC_LOOP_CLAUSES | OACC_KERNELS_CLAUSES)
    4587              : #define OACC_SERIAL_LOOP_CLAUSES \
    4588              :   (OACC_LOOP_CLAUSES | OACC_SERIAL_CLAUSES)
    4589              : #define OACC_HOST_DATA_CLAUSES \
    4590              :   (omp_mask (OMP_CLAUSE_USE_DEVICE)                                           \
    4591              :    | OMP_CLAUSE_IF                                                            \
    4592              :    | OMP_CLAUSE_IF_PRESENT)
    4593              : #define OACC_DECLARE_CLAUSES \
    4594              :   (omp_mask (OMP_CLAUSE_COPY) | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT        \
    4595              :    | OMP_CLAUSE_CREATE | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_DEVICE_RESIDENT    \
    4596              :    | OMP_CLAUSE_PRESENT                       \
    4597              :    | OMP_CLAUSE_LINK)
    4598              : #define OACC_UPDATE_CLAUSES                                             \
    4599              :   (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_HOST              \
    4600              :    | OMP_CLAUSE_DEVICE | OMP_CLAUSE_WAIT | OMP_CLAUSE_IF_PRESENT              \
    4601              :    | OMP_CLAUSE_SELF)
    4602              : #define OACC_ENTER_DATA_CLAUSES \
    4603              :   (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_WAIT              \
    4604              :    | OMP_CLAUSE_COPYIN | OMP_CLAUSE_CREATE | OMP_CLAUSE_ATTACH)
    4605              : #define OACC_EXIT_DATA_CLAUSES \
    4606              :   (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_WAIT              \
    4607              :    | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_DELETE | OMP_CLAUSE_FINALIZE             \
    4608              :    | OMP_CLAUSE_DETACH)
    4609              : #define OACC_WAIT_CLAUSES \
    4610              :   omp_mask (OMP_CLAUSE_ASYNC) | OMP_CLAUSE_IF
    4611              : #define OACC_ROUTINE_CLAUSES \
    4612              :   (omp_mask (OMP_CLAUSE_GANG) | OMP_CLAUSE_WORKER | OMP_CLAUSE_VECTOR         \
    4613              :    | OMP_CLAUSE_SEQ                                                           \
    4614              :    | OMP_CLAUSE_NOHOST)
    4615              : 
    4616              : 
    4617              : static match
    4618        11796 : match_acc (gfc_exec_op op, const omp_mask mask)
    4619              : {
    4620        11796 :   gfc_omp_clauses *c;
    4621        11796 :   if (gfc_match_omp_clauses (&c, mask, false, false, true) != MATCH_YES)
    4622              :     return MATCH_ERROR;
    4623        11591 :   new_st.op = op;
    4624        11591 :   new_st.ext.omp_clauses = c;
    4625        11591 :   return MATCH_YES;
    4626              : }
    4627              : 
    4628              : match
    4629         1378 : gfc_match_oacc_parallel_loop (void)
    4630              : {
    4631         1378 :   return match_acc (EXEC_OACC_PARALLEL_LOOP, OACC_PARALLEL_LOOP_CLAUSES);
    4632              : }
    4633              : 
    4634              : 
    4635              : match
    4636         2974 : gfc_match_oacc_parallel (void)
    4637              : {
    4638         2974 :   return match_acc (EXEC_OACC_PARALLEL, OACC_PARALLEL_CLAUSES);
    4639              : }
    4640              : 
    4641              : 
    4642              : match
    4643          129 : gfc_match_oacc_kernels_loop (void)
    4644              : {
    4645          129 :   return match_acc (EXEC_OACC_KERNELS_LOOP, OACC_KERNELS_LOOP_CLAUSES);
    4646              : }
    4647              : 
    4648              : 
    4649              : match
    4650          904 : gfc_match_oacc_kernels (void)
    4651              : {
    4652          904 :   return match_acc (EXEC_OACC_KERNELS, OACC_KERNELS_CLAUSES);
    4653              : }
    4654              : 
    4655              : 
    4656              : match
    4657          230 : gfc_match_oacc_serial_loop (void)
    4658              : {
    4659          230 :   return match_acc (EXEC_OACC_SERIAL_LOOP, OACC_SERIAL_LOOP_CLAUSES);
    4660              : }
    4661              : 
    4662              : 
    4663              : match
    4664          359 : gfc_match_oacc_serial (void)
    4665              : {
    4666          359 :   return match_acc (EXEC_OACC_SERIAL, OACC_SERIAL_CLAUSES);
    4667              : }
    4668              : 
    4669              : 
    4670              : match
    4671          689 : gfc_match_oacc_data (void)
    4672              : {
    4673          689 :   return match_acc (EXEC_OACC_DATA, OACC_DATA_CLAUSES);
    4674              : }
    4675              : 
    4676              : 
    4677              : match
    4678           65 : gfc_match_oacc_host_data (void)
    4679              : {
    4680           65 :   return match_acc (EXEC_OACC_HOST_DATA, OACC_HOST_DATA_CLAUSES);
    4681              : }
    4682              : 
    4683              : 
    4684              : match
    4685         3583 : gfc_match_oacc_loop (void)
    4686              : {
    4687         3583 :   return match_acc (EXEC_OACC_LOOP, OACC_LOOP_CLAUSES);
    4688              : }
    4689              : 
    4690              : 
    4691              : match
    4692          176 : gfc_match_oacc_declare (void)
    4693              : {
    4694          176 :   gfc_omp_clauses *c;
    4695          176 :   gfc_omp_namelist *n;
    4696          176 :   gfc_namespace *ns = gfc_current_ns;
    4697          176 :   gfc_oacc_declare *new_oc;
    4698          176 :   bool module_var = false;
    4699          176 :   locus where = gfc_current_locus;
    4700              : 
    4701          176 :   if (gfc_match_omp_clauses (&c, OACC_DECLARE_CLAUSES, false, false, true)
    4702              :       != MATCH_YES)
    4703              :     return MATCH_ERROR;
    4704              : 
    4705          260 :   for (n = c->lists[OMP_LIST_DEVICE_RESIDENT]; n != NULL; n = n->next)
    4706           90 :     n->sym->attr.oacc_declare_device_resident = 1;
    4707              : 
    4708          190 :   for (n = c->lists[OMP_LIST_LINK]; n != NULL; n = n->next)
    4709           20 :     n->sym->attr.oacc_declare_link = 1;
    4710              : 
    4711          312 :   for (n = c->lists[OMP_LIST_MAP]; n != NULL; n = n->next)
    4712              :     {
    4713          152 :       gfc_symbol *s = n->sym;
    4714              : 
    4715          152 :       if (gfc_current_ns->proc_name
    4716          152 :           && gfc_current_ns->proc_name->attr.flavor == FL_MODULE)
    4717              :         {
    4718           48 :           if (n->u.map.op != OMP_MAP_ALLOC && n->u.map.op != OMP_MAP_TO)
    4719              :             {
    4720            6 :               gfc_error ("Invalid clause in module with !$ACC DECLARE at %L",
    4721              :                          &where);
    4722            6 :               return MATCH_ERROR;
    4723              :             }
    4724              : 
    4725              :           module_var = true;
    4726              :         }
    4727              : 
    4728          146 :       if (s->attr.use_assoc)
    4729              :         {
    4730            0 :           gfc_error ("Variable is USE-associated with !$ACC DECLARE at %L",
    4731              :                      &where);
    4732            0 :           return MATCH_ERROR;
    4733              :         }
    4734              : 
    4735          146 :       if ((s->result == s && s->ns->contained != gfc_current_ns)
    4736          146 :           || ((s->attr.flavor == FL_UNKNOWN || s->attr.flavor == FL_VARIABLE)
    4737          131 :               && s->ns != gfc_current_ns))
    4738              :         {
    4739            2 :           gfc_error ("Variable %qs shall be declared in the same scoping unit "
    4740              :                      "as !$ACC DECLARE at %L", s->name, &where);
    4741            2 :           return MATCH_ERROR;
    4742              :         }
    4743              : 
    4744          144 :       if ((s->attr.dimension || s->attr.codimension)
    4745           76 :           && s->attr.dummy && s->as->type != AS_EXPLICIT)
    4746              :         {
    4747            2 :           gfc_error ("Assumed-size dummy array with !$ACC DECLARE at %L",
    4748              :                      &where);
    4749            2 :           return MATCH_ERROR;
    4750              :         }
    4751              : 
    4752          142 :       switch (n->u.map.op)
    4753              :         {
    4754           49 :           case OMP_MAP_FORCE_ALLOC:
    4755           49 :           case OMP_MAP_ALLOC:
    4756           49 :             s->attr.oacc_declare_create = 1;
    4757           49 :             break;
    4758              : 
    4759           59 :           case OMP_MAP_FORCE_TO:
    4760           59 :           case OMP_MAP_TO:
    4761           59 :             s->attr.oacc_declare_copyin = 1;
    4762           59 :             break;
    4763              : 
    4764            1 :           case OMP_MAP_FORCE_DEVICEPTR:
    4765            1 :             s->attr.oacc_declare_deviceptr = 1;
    4766            1 :             break;
    4767              : 
    4768              :           default:
    4769              :             break;
    4770              :         }
    4771              :     }
    4772              : 
    4773          160 :   new_oc = gfc_get_oacc_declare ();
    4774          160 :   new_oc->next = ns->oacc_declare;
    4775          160 :   new_oc->module_var = module_var;
    4776          160 :   new_oc->clauses = c;
    4777          160 :   new_oc->loc = gfc_current_locus;
    4778          160 :   ns->oacc_declare = new_oc;
    4779              : 
    4780          160 :   return MATCH_YES;
    4781              : }
    4782              : 
    4783              : 
    4784              : match
    4785          760 : gfc_match_oacc_update (void)
    4786              : {
    4787          760 :   gfc_omp_clauses *c;
    4788          760 :   locus here = gfc_current_locus;
    4789              : 
    4790          760 :   if (gfc_match_omp_clauses (&c, OACC_UPDATE_CLAUSES, false, false, true)
    4791              :       != MATCH_YES)
    4792              :     return MATCH_ERROR;
    4793              : 
    4794          756 :   if (!c->lists[OMP_LIST_MAP])
    4795              :     {
    4796            1 :       gfc_error ("%<acc update%> must contain at least one "
    4797              :                  "%<device%> or %<host%> or %<self%> clause at %L", &here);
    4798            1 :       return MATCH_ERROR;
    4799              :     }
    4800              : 
    4801          755 :   new_st.op = EXEC_OACC_UPDATE;
    4802          755 :   new_st.ext.omp_clauses = c;
    4803          755 :   return MATCH_YES;
    4804              : }
    4805              : 
    4806              : 
    4807              : match
    4808          875 : gfc_match_oacc_enter_data (void)
    4809              : {
    4810          875 :   return match_acc (EXEC_OACC_ENTER_DATA, OACC_ENTER_DATA_CLAUSES);
    4811              : }
    4812              : 
    4813              : 
    4814              : match
    4815          610 : gfc_match_oacc_exit_data (void)
    4816              : {
    4817          610 :   return match_acc (EXEC_OACC_EXIT_DATA, OACC_EXIT_DATA_CLAUSES);
    4818              : }
    4819              : 
    4820              : 
    4821              : match
    4822          203 : gfc_match_oacc_wait (void)
    4823              : {
    4824          203 :   gfc_omp_clauses *c = gfc_get_omp_clauses ();
    4825          203 :   gfc_expr_list *wait_list = NULL, *el;
    4826          203 :   bool space = true;
    4827          203 :   match m;
    4828              : 
    4829          203 :   m = match_omp_oacc_expr_list (" (", &wait_list, true, false);
    4830          203 :   if (m == MATCH_ERROR)
    4831              :     return m;
    4832          197 :   else if (m == MATCH_YES)
    4833          126 :     space = false;
    4834              : 
    4835          197 :   if (gfc_match_omp_clauses (&c, OACC_WAIT_CLAUSES, space, space, true)
    4836              :       == MATCH_ERROR)
    4837              :     return MATCH_ERROR;
    4838              : 
    4839          184 :   if (wait_list)
    4840          261 :     for (el = wait_list; el; el = el->next)
    4841              :       {
    4842          140 :         if (el->expr == NULL)
    4843              :           {
    4844            2 :             gfc_error ("Invalid argument to !$ACC WAIT at %C");
    4845            2 :             return MATCH_ERROR;
    4846              :           }
    4847              : 
    4848          138 :         if (!gfc_resolve_expr (el->expr)
    4849          138 :             || el->expr->ts.type != BT_INTEGER || el->expr->rank != 0)
    4850              :           {
    4851            3 :             gfc_error ("WAIT clause at %L requires a scalar INTEGER expression",
    4852            3 :                        &el->expr->where);
    4853              : 
    4854            3 :             return MATCH_ERROR;
    4855              :           }
    4856              :       }
    4857          179 :   c->wait_list = wait_list;
    4858          179 :   new_st.op = EXEC_OACC_WAIT;
    4859          179 :   new_st.ext.omp_clauses = c;
    4860          179 :   return MATCH_YES;
    4861              : }
    4862              : 
    4863              : 
    4864              : match
    4865           97 : gfc_match_oacc_cache (void)
    4866              : {
    4867           97 :   bool readonly = false;
    4868           97 :   gfc_omp_clauses *c = gfc_get_omp_clauses ();
    4869              :   /* The OpenACC cache directive explicitly only allows "array elements or
    4870              :      subarrays", which we're currently not checking here.  Either check this
    4871              :      after the call of gfc_match_omp_variable_list, or add something like a
    4872              :      only_sections variant next to its allow_sections parameter.  */
    4873           97 :   match m = gfc_match (" ( ");
    4874           97 :   if (m != MATCH_YES)
    4875              :     {
    4876            0 :       gfc_free_omp_clauses(c);
    4877            0 :       return m;
    4878              :     }
    4879              : 
    4880           97 :   if (gfc_match ("readonly : ") == MATCH_YES)
    4881            8 :     readonly = true;
    4882              : 
    4883           97 :   gfc_omp_namelist **head = NULL;
    4884           97 :   m = gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_CACHE], true,
    4885              :                                    NULL, &head, true);
    4886           97 :   if (m != MATCH_YES)
    4887              :     {
    4888            2 :       gfc_free_omp_clauses(c);
    4889            2 :       return m;
    4890              :     }
    4891              : 
    4892           95 :   if (readonly)
    4893           24 :     for (gfc_omp_namelist *n = *head; n; n = n->next)
    4894           16 :       n->u.map.readonly = true;
    4895              : 
    4896           95 :   if (gfc_current_state() != COMP_DO
    4897           56 :       && gfc_current_state() != COMP_DO_CONCURRENT)
    4898              :     {
    4899            2 :       gfc_error ("ACC CACHE directive must be inside of loop %C");
    4900            2 :       gfc_free_omp_clauses(c);
    4901            2 :       return MATCH_ERROR;
    4902              :     }
    4903              : 
    4904           93 :   new_st.op = EXEC_OACC_CACHE;
    4905           93 :   new_st.ext.omp_clauses = c;
    4906           93 :   return MATCH_YES;
    4907              : }
    4908              : 
    4909              : /* Determine the OpenACC 'routine' directive's level of parallelism.  */
    4910              : 
    4911              : static oacc_routine_lop
    4912          734 : gfc_oacc_routine_lop (gfc_omp_clauses *clauses)
    4913              : {
    4914          734 :   oacc_routine_lop ret = OACC_ROUTINE_LOP_SEQ;
    4915              : 
    4916          734 :   if (clauses)
    4917              :     {
    4918          584 :       unsigned n_lop_clauses = 0;
    4919              : 
    4920          584 :       if (clauses->gang)
    4921              :         {
    4922          164 :           ++n_lop_clauses;
    4923          164 :           ret = OACC_ROUTINE_LOP_GANG;
    4924              :         }
    4925          584 :       if (clauses->worker)
    4926              :         {
    4927          114 :           ++n_lop_clauses;
    4928          114 :           ret = OACC_ROUTINE_LOP_WORKER;
    4929              :         }
    4930          584 :       if (clauses->vector)
    4931              :         {
    4932          116 :           ++n_lop_clauses;
    4933          116 :           ret = OACC_ROUTINE_LOP_VECTOR;
    4934              :         }
    4935          584 :       if (clauses->seq)
    4936              :         {
    4937          206 :           ++n_lop_clauses;
    4938          206 :           ret = OACC_ROUTINE_LOP_SEQ;
    4939              :         }
    4940              : 
    4941          584 :       if (n_lop_clauses > 1)
    4942           47 :         ret = OACC_ROUTINE_LOP_ERROR;
    4943              :     }
    4944              : 
    4945          734 :   return ret;
    4946              : }
    4947              : 
    4948              : match
    4949          698 : gfc_match_oacc_routine (void)
    4950              : {
    4951          698 :   locus old_loc;
    4952          698 :   match m;
    4953          698 :   gfc_intrinsic_sym *isym = NULL;
    4954          698 :   gfc_symbol *sym = NULL;
    4955          698 :   gfc_omp_clauses *c = NULL;
    4956          698 :   gfc_oacc_routine_name *n = NULL;
    4957          698 :   oacc_routine_lop lop = OACC_ROUTINE_LOP_NONE;
    4958          698 :   bool nohost;
    4959              : 
    4960          698 :   old_loc = gfc_current_locus;
    4961              : 
    4962          698 :   m = gfc_match (" (");
    4963              : 
    4964          698 :   if (gfc_current_ns->proc_name
    4965          696 :       && gfc_current_ns->proc_name->attr.if_source == IFSRC_IFBODY
    4966           90 :       && m == MATCH_YES)
    4967              :     {
    4968            3 :       gfc_error ("Only the !$ACC ROUTINE form without "
    4969              :                  "list is allowed in interface block at %C");
    4970            3 :       goto cleanup;
    4971              :     }
    4972              : 
    4973          608 :   if (m == MATCH_YES)
    4974              :     {
    4975          295 :       char buffer[GFC_MAX_SYMBOL_LEN + 1];
    4976              : 
    4977          295 :       m = gfc_match_name (buffer);
    4978          295 :       if (m == MATCH_YES)
    4979              :         {
    4980          294 :           gfc_symtree *st = NULL;
    4981              : 
    4982              :           /* First look for an intrinsic symbol.  */
    4983          294 :           isym = gfc_find_function (buffer);
    4984          294 :           if (!isym)
    4985          294 :             isym = gfc_find_subroutine (buffer);
    4986              :           /* If no intrinsic symbol found, search the current namespace.  */
    4987          294 :           if (!isym)
    4988          276 :             st = gfc_find_symtree (gfc_current_ns->sym_root, buffer);
    4989          276 :           if (st)
    4990              :             {
    4991          270 :               sym = st->n.sym;
    4992              :               /* If the name in a 'routine' directive refers to the containing
    4993              :                  subroutine or function, then make sure that we'll later handle
    4994              :                  this accordingly.  */
    4995          270 :               if (gfc_current_ns->proc_name != NULL
    4996          270 :                   && strcmp (sym->name, gfc_current_ns->proc_name->name) == 0)
    4997          294 :                 sym = NULL;
    4998              :             }
    4999              : 
    5000          294 :           if (isym == NULL && st == NULL)
    5001              :             {
    5002            6 :               gfc_error ("Invalid NAME %qs in !$ACC ROUTINE ( NAME ) at %C",
    5003              :                          buffer);
    5004            6 :               gfc_current_locus = old_loc;
    5005            9 :               return MATCH_ERROR;
    5006              :             }
    5007              :         }
    5008              :       else
    5009              :         {
    5010            1 :           gfc_error ("Syntax error in !$ACC ROUTINE ( NAME ) at %C");
    5011            1 :           gfc_current_locus = old_loc;
    5012            1 :           return MATCH_ERROR;
    5013              :         }
    5014              : 
    5015          288 :       if (gfc_match_char (')') != MATCH_YES)
    5016              :         {
    5017            2 :           gfc_error ("Syntax error in !$ACC ROUTINE ( NAME ) at %C, expecting"
    5018              :                      " %<)%> after NAME");
    5019            2 :           gfc_current_locus = old_loc;
    5020            2 :           return MATCH_ERROR;
    5021              :         }
    5022              :     }
    5023              : 
    5024          686 :   if (gfc_match_omp_eos () != MATCH_YES
    5025          686 :       && (gfc_match_omp_clauses (&c, OACC_ROUTINE_CLAUSES, false, false, true)
    5026              :           != MATCH_YES))
    5027              :     return MATCH_ERROR;
    5028              : 
    5029          683 :   lop = gfc_oacc_routine_lop (c);
    5030          683 :   if (lop == OACC_ROUTINE_LOP_ERROR)
    5031              :     {
    5032           47 :       gfc_error ("Multiple loop axes specified for routine at %C");
    5033           47 :       goto cleanup;
    5034              :     }
    5035          636 :   nohost = c ? c->nohost : false;
    5036              : 
    5037          636 :   if (isym != NULL)
    5038              :     {
    5039              :       /* Diagnose any OpenACC 'routine' directive that doesn't match the
    5040              :          (implicit) one with a 'seq' clause.  */
    5041           16 :       if (c && (c->gang || c->worker || c->vector))
    5042              :         {
    5043           10 :           gfc_error ("Intrinsic symbol specified in !$ACC ROUTINE ( NAME )"
    5044              :                      " at %C marked with incompatible GANG, WORKER, or VECTOR"
    5045              :                      " clause");
    5046           10 :           goto cleanup;
    5047              :         }
    5048              :       /* ..., and no 'nohost' clause.  */
    5049            6 :       if (nohost)
    5050              :         {
    5051            2 :           gfc_error ("Intrinsic symbol specified in !$ACC ROUTINE ( NAME )"
    5052              :                      " at %C marked with incompatible NOHOST clause");
    5053            2 :           goto cleanup;
    5054              :         }
    5055              :     }
    5056          620 :   else if (sym != NULL)
    5057              :     {
    5058          151 :       bool add = true;
    5059              : 
    5060              :       /* For a repeated OpenACC 'routine' directive, diagnose if it doesn't
    5061              :          match the first one.  */
    5062          151 :       for (gfc_oacc_routine_name *n_p = gfc_current_ns->oacc_routine_names;
    5063          346 :            n_p;
    5064          195 :            n_p = n_p->next)
    5065          235 :         if (n_p->sym == sym)
    5066              :           {
    5067           51 :             add = false;
    5068           51 :             bool nohost_p = n_p->clauses ? n_p->clauses->nohost : false;
    5069           51 :             if (lop != gfc_oacc_routine_lop (n_p->clauses)
    5070           51 :                 || nohost != nohost_p)
    5071              :               {
    5072           40 :                 gfc_error ("!$ACC ROUTINE already applied at %C");
    5073           40 :                 goto cleanup;
    5074              :               }
    5075              :           }
    5076              : 
    5077          111 :       if (add)
    5078              :         {
    5079          100 :           sym->attr.oacc_routine_lop = lop;
    5080          100 :           sym->attr.oacc_routine_nohost = nohost;
    5081              : 
    5082          100 :           n = gfc_get_oacc_routine_name ();
    5083          100 :           n->sym = sym;
    5084          100 :           n->clauses = c;
    5085          100 :           n->next = gfc_current_ns->oacc_routine_names;
    5086          100 :           n->loc = old_loc;
    5087          100 :           gfc_current_ns->oacc_routine_names = n;
    5088              :         }
    5089              :     }
    5090          469 :   else if (gfc_current_ns->proc_name)
    5091              :     {
    5092              :       /* For a repeated OpenACC 'routine' directive, diagnose if it doesn't
    5093              :          match the first one.  */
    5094          468 :       oacc_routine_lop lop_p = gfc_current_ns->proc_name->attr.oacc_routine_lop;
    5095          468 :       bool nohost_p = gfc_current_ns->proc_name->attr.oacc_routine_nohost;
    5096          468 :       if (lop_p != OACC_ROUTINE_LOP_NONE
    5097           86 :           && (lop != lop_p
    5098           86 :               || nohost != nohost_p))
    5099              :         {
    5100           56 :           gfc_error ("!$ACC ROUTINE already applied at %C");
    5101           56 :           goto cleanup;
    5102              :         }
    5103              : 
    5104          412 :       if (!gfc_add_omp_declare_target (&gfc_current_ns->proc_name->attr,
    5105              :                                        gfc_current_ns->proc_name->name,
    5106              :                                        &old_loc))
    5107            1 :         goto cleanup;
    5108          411 :       gfc_current_ns->proc_name->attr.oacc_routine_lop = lop;
    5109          411 :       gfc_current_ns->proc_name->attr.oacc_routine_nohost = nohost;
    5110              :     }
    5111              :   else
    5112              :     /* Something has gone wrong, possibly a syntax error.  */
    5113            1 :     goto cleanup;
    5114              : 
    5115          526 :   if (gfc_pure (NULL) && c && (c->gang || c->worker || c->vector))
    5116              :     {
    5117            6 :       gfc_error ("!$ACC ROUTINE with GANG, WORKER, or VECTOR clause is not "
    5118              :                  "permitted in PURE procedure at %C");
    5119            6 :       goto cleanup;
    5120              :     }
    5121              : 
    5122              : 
    5123          520 :   if (n)
    5124          100 :     n->clauses = c;
    5125          420 :   else if (gfc_current_ns->oacc_routine)
    5126            0 :     gfc_current_ns->oacc_routine_clauses = c;
    5127              : 
    5128          520 :   new_st.op = EXEC_OACC_ROUTINE;
    5129          520 :   new_st.ext.omp_clauses = c;
    5130          520 :   return MATCH_YES;
    5131              : 
    5132          166 : cleanup:
    5133          166 :   gfc_current_locus = old_loc;
    5134          166 :   return MATCH_ERROR;
    5135              : }
    5136              : 
    5137              : 
    5138              : #define OMP_PARALLEL_CLAUSES \
    5139              :   (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE              \
    5140              :    | OMP_CLAUSE_SHARED | OMP_CLAUSE_COPYIN | OMP_CLAUSE_REDUCTION       \
    5141              :    | OMP_CLAUSE_IF | OMP_CLAUSE_NUM_THREADS | OMP_CLAUSE_DEFAULT        \
    5142              :    | OMP_CLAUSE_PROC_BIND | OMP_CLAUSE_ALLOCATE)
    5143              : #define OMP_DECLARE_SIMD_CLAUSES \
    5144              :   (omp_mask (OMP_CLAUSE_SIMDLEN) | OMP_CLAUSE_LINEAR                    \
    5145              :    | OMP_CLAUSE_UNIFORM | OMP_CLAUSE_ALIGNED | OMP_CLAUSE_INBRANCH      \
    5146              :    | OMP_CLAUSE_NOTINBRANCH)
    5147              : #define OMP_DO_CLAUSES \
    5148              :   (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE              \
    5149              :    | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION                      \
    5150              :    | OMP_CLAUSE_SCHEDULE | OMP_CLAUSE_ORDERED | OMP_CLAUSE_COLLAPSE     \
    5151              :    | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE         \
    5152              :    | OMP_CLAUSE_NOWAIT)
    5153              : #define OMP_LOOP_CLAUSES \
    5154              :   (omp_mask (OMP_CLAUSE_BIND) | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_ORDER  \
    5155              :    | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION)
    5156              : 
    5157              : #define OMP_SCOPE_CLAUSES \
    5158              :   (omp_mask (OMP_CLAUSE_PRIVATE) |OMP_CLAUSE_FIRSTPRIVATE               \
    5159              :    | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT)
    5160              : #define OMP_SECTIONS_CLAUSES \
    5161              :   (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE              \
    5162              :    | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION                      \
    5163              :    | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT)
    5164              : #define OMP_SIMD_CLAUSES \
    5165              :   (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_LASTPRIVATE               \
    5166              :    | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_SAFELEN    \
    5167              :    | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ALIGNED | OMP_CLAUSE_SIMDLEN        \
    5168              :    | OMP_CLAUSE_IF | OMP_CLAUSE_ORDER | OMP_CLAUSE_NOTEMPORAL)
    5169              : #define OMP_TASK_CLAUSES \
    5170              :   (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE              \
    5171              :    | OMP_CLAUSE_SHARED | OMP_CLAUSE_IF | OMP_CLAUSE_DEFAULT             \
    5172              :    | OMP_CLAUSE_UNTIED | OMP_CLAUSE_FINAL | OMP_CLAUSE_MERGEABLE        \
    5173              :    | OMP_CLAUSE_DEPEND | OMP_CLAUSE_PRIORITY | OMP_CLAUSE_IN_REDUCTION  \
    5174              :    | OMP_CLAUSE_DETACH | OMP_CLAUSE_AFFINITY | OMP_CLAUSE_ALLOCATE)
    5175              : #define OMP_TASKLOOP_CLAUSES \
    5176              :   (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE              \
    5177              :    | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_IF         \
    5178              :    | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_UNTIED | OMP_CLAUSE_FINAL          \
    5179              :    | OMP_CLAUSE_MERGEABLE | OMP_CLAUSE_PRIORITY | OMP_CLAUSE_GRAINSIZE  \
    5180              :    | OMP_CLAUSE_NUM_TASKS | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_NOGROUP    \
    5181              :    | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_IN_REDUCTION | OMP_CLAUSE_ALLOCATE)
    5182              : #define OMP_TASKGROUP_CLAUSES \
    5183              :   (omp_mask (OMP_CLAUSE_TASK_REDUCTION) | OMP_CLAUSE_ALLOCATE)
    5184              : #define OMP_TARGET_CLAUSES \
    5185              :   (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF        \
    5186              :    | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_PRIVATE         \
    5187              :    | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULTMAP                    \
    5188              :    | OMP_CLAUSE_IS_DEVICE_PTR | OMP_CLAUSE_IN_REDUCTION                 \
    5189              :    | OMP_CLAUSE_THREAD_LIMIT | OMP_CLAUSE_ALLOCATE                      \
    5190              :    | OMP_CLAUSE_HAS_DEVICE_ADDR | OMP_CLAUSE_USES_ALLOCATORS            \
    5191              :    | OMP_CLAUSE_DYN_GROUPPRIVATE | OMP_CLAUSE_DEVICE_TYPE)
    5192              : #define OMP_TARGET_DATA_CLAUSES \
    5193              :   (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF        \
    5194              :    | OMP_CLAUSE_USE_DEVICE_PTR | OMP_CLAUSE_USE_DEVICE_ADDR)
    5195              : #define OMP_TARGET_ENTER_DATA_CLAUSES \
    5196              :   (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF        \
    5197              :    | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT)
    5198              : #define OMP_TARGET_EXIT_DATA_CLAUSES \
    5199              :   (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF        \
    5200              :    | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT)
    5201              : #define OMP_TARGET_UPDATE_CLAUSES \
    5202              :   (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_IF | OMP_CLAUSE_TO         \
    5203              :    | OMP_CLAUSE_FROM | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT)
    5204              : #define OMP_TEAMS_CLAUSES \
    5205              :   (omp_mask (OMP_CLAUSE_NUM_TEAMS) | OMP_CLAUSE_THREAD_LIMIT            \
    5206              :    | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE  \
    5207              :    | OMP_CLAUSE_SHARED | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_ALLOCATE)
    5208              : #define OMP_DISTRIBUTE_CLAUSES \
    5209              :   (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE              \
    5210              :    | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_DIST_SCHEDULE \
    5211              :    | OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE)
    5212              : #define OMP_SINGLE_CLAUSES \
    5213              :   (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE              \
    5214              :    | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_COPYPRIVATE)
    5215              : #define OMP_ORDERED_CLAUSES \
    5216              :   (omp_mask (OMP_CLAUSE_THREADS) | OMP_CLAUSE_SIMD)
    5217              : #define OMP_DECLARE_TARGET_CLAUSES \
    5218              :   (omp_mask (OMP_CLAUSE_ENTER) | OMP_CLAUSE_LINK | OMP_CLAUSE_DEVICE_TYPE \
    5219              :    | OMP_CLAUSE_TO | OMP_CLAUSE_INDIRECT | OMP_CLAUSE_LOCAL)
    5220              : #define OMP_ATOMIC_CLAUSES \
    5221              :   (omp_mask (OMP_CLAUSE_ATOMIC) | OMP_CLAUSE_CAPTURE | OMP_CLAUSE_HINT  \
    5222              :    | OMP_CLAUSE_MEMORDER | OMP_CLAUSE_COMPARE | OMP_CLAUSE_FAIL         \
    5223              :    | OMP_CLAUSE_WEAK)
    5224              : #define OMP_MASKED_CLAUSES \
    5225              :   (omp_mask (OMP_CLAUSE_FILTER))
    5226              : #define OMP_ERROR_CLAUSES \
    5227              :   (omp_mask (OMP_CLAUSE_AT) | OMP_CLAUSE_MESSAGE | OMP_CLAUSE_SEVERITY)
    5228              : #define OMP_WORKSHARE_CLAUSES \
    5229              :   omp_mask (OMP_CLAUSE_NOWAIT)
    5230              : #define OMP_UNROLL_CLAUSES \
    5231              :   (omp_mask (OMP_CLAUSE_FULL) | OMP_CLAUSE_PARTIAL)
    5232              : #define OMP_TILE_CLAUSES \
    5233              :   (omp_mask (OMP_CLAUSE_SIZES))
    5234              : #define OMP_ALLOCATORS_CLAUSES \
    5235              :   omp_mask (OMP_CLAUSE_ALLOCATE)
    5236              : #define OMP_INTEROP_CLAUSES \
    5237              :   (omp_mask (OMP_CLAUSE_DEPEND) | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_DEVICE \
    5238              :    | OMP_CLAUSE_INIT | OMP_CLAUSE_DESTROY | OMP_CLAUSE_USE)
    5239              : #define OMP_DISPATCH_CLAUSES                                                   \
    5240              :   (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOVARIANTS    \
    5241              :    | OMP_CLAUSE_NOCONTEXT | OMP_CLAUSE_IS_DEVICE_PTR | OMP_CLAUSE_NOWAIT       \
    5242              :    | OMP_CLAUSE_HAS_DEVICE_ADDR | OMP_CLAUSE_INTEROP)
    5243              : 
    5244              : 
    5245              : static match
    5246        16767 : match_omp (gfc_exec_op op, const omp_mask mask)
    5247              : {
    5248        16767 :   gfc_omp_clauses *c;
    5249        16767 :   if (gfc_match_omp_clauses (&c, mask, true, true, false,
    5250              :                              op == EXEC_OMP_TARGET) != MATCH_YES)
    5251              :     return MATCH_ERROR;
    5252        16519 :   new_st.op = op;
    5253        16519 :   new_st.ext.omp_clauses = c;
    5254        16519 :   return MATCH_YES;
    5255              : }
    5256              : 
    5257              : /* Handles both declarative and (deprecated) executable ALLOCATE directive;
    5258              :    accepts optional list (for executable) and common blocks.
    5259              :    If no variables have been provided, the single omp namelist has sym == NULL.
    5260              : 
    5261              :    Note that the executable ALLOCATE directive permits structure elements only
    5262              :    in OpenMP 5.0 and 5.1 but not longer in 5.2.  See also the comment on the
    5263              :    'omp allocators' directive below. The accidental change was reverted for
    5264              :    OpenMP TR12, permitting them again. See also gfc_match_omp_allocators.
    5265              : 
    5266              :    Hence, structure elements are rejected for now, also to make resolving
    5267              :    OMP_LIST_ALLOCATE simpler (check for duplicates, same symbol in
    5268              :    Fortran allocate stmt).  TODO: Permit structure elements.  */
    5269              : 
    5270              : match
    5271          274 : gfc_match_omp_allocate (void)
    5272              : {
    5273          274 :   match m;
    5274          274 :   bool first = true;
    5275          274 :   gfc_omp_namelist *vars = NULL;
    5276          274 :   gfc_expr *align = NULL;
    5277          274 :   gfc_expr *allocator = NULL;
    5278          274 :   locus loc = gfc_current_locus;
    5279              : 
    5280          274 :   m = gfc_match_omp_variable_list (" (", &vars, true, NULL, NULL, true, true,
    5281              :                                    NULL, true);
    5282              : 
    5283          274 :   if (m == MATCH_ERROR)
    5284              :     return m;
    5285              : 
    5286          502 :   while (true)
    5287              :     {
    5288          502 :       gfc_gobble_whitespace ();
    5289          502 :       if (gfc_match_omp_eos () == MATCH_YES)
    5290              :         break;
    5291          234 :       if (!first)
    5292           28 :         gfc_match (", ");
    5293          234 :       first = false;
    5294          234 :       if ((m = gfc_match_dupl_check (!align, "align", true, &align))
    5295              :           != MATCH_NO)
    5296              :         {
    5297           62 :           if (m == MATCH_ERROR)
    5298            1 :             goto error;
    5299           61 :           continue;
    5300              :         }
    5301          172 :       if ((m = gfc_match_dupl_check (!allocator, "allocator",
    5302              :                                      true, &allocator)) != MATCH_NO)
    5303              :         {
    5304          171 :           if (m == MATCH_ERROR)
    5305            1 :             goto error;
    5306          170 :           continue;
    5307              :         }
    5308            1 :       gfc_error ("Expected ALIGN or ALLOCATOR clause at %C");
    5309            1 :       return MATCH_ERROR;
    5310              :     }
    5311          541 :   for (gfc_omp_namelist *n = vars; n; n = n->next)
    5312          276 :     if (n->expr)
    5313              :       {
    5314            3 :         if ((n->expr->ref && n->expr->ref->type == REF_COMPONENT)
    5315            3 :             || (n->expr->ref->next && n->expr->ref->type == REF_COMPONENT))
    5316            1 :           gfc_error ("Sorry, structure-element list item at %L in ALLOCATE "
    5317              :                      "directive is not yet supported", &n->expr->where);
    5318              :         else
    5319            2 :           gfc_error ("Unexpected expression as list item at %L in ALLOCATE "
    5320              :                      "directive", &n->expr->where);
    5321              : 
    5322            3 :         gfc_free_omp_namelist (vars, false, true, false, false);
    5323            3 :         goto error;
    5324              :       }
    5325              : 
    5326          265 :   new_st.op = EXEC_OMP_ALLOCATE;
    5327          265 :   new_st.ext.omp_clauses = gfc_get_omp_clauses ();
    5328          265 :   if (vars == NULL)
    5329              :     {
    5330           27 :       vars = gfc_get_omp_namelist ();
    5331           27 :       vars->where = loc;
    5332           27 :       vars->u.align = align;
    5333           27 :       vars->u2.allocator = allocator;
    5334           27 :       new_st.ext.omp_clauses->lists[OMP_LIST_ALLOCATE] = vars;
    5335              :     }
    5336              :   else
    5337              :     {
    5338          238 :       new_st.ext.omp_clauses->lists[OMP_LIST_ALLOCATE] = vars;
    5339          511 :       for (; vars; vars = vars->next)
    5340              :         {
    5341          273 :           vars->u.align = (align) ? gfc_copy_expr (align) : NULL;
    5342          273 :           vars->u2.allocator = allocator;
    5343              :         }
    5344          238 :       gfc_free_expr (align);
    5345              :     }
    5346              :   return MATCH_YES;
    5347              : 
    5348            5 : error:
    5349            5 :   gfc_free_expr (align);
    5350            5 :   gfc_free_expr (allocator);
    5351            5 :   return MATCH_ERROR;
    5352              : }
    5353              : 
    5354              : /* In line with OpenMP 5.2 derived-type components are rejected.
    5355              :    See also comment before gfc_match_omp_allocate.  */
    5356              : 
    5357              : match
    5358           26 : gfc_match_omp_allocators (void)
    5359              : {
    5360           26 :   return match_omp (EXEC_OMP_ALLOCATORS, OMP_ALLOCATORS_CLAUSES);
    5361              : }
    5362              : 
    5363              : 
    5364              : match
    5365           22 : gfc_match_omp_assume (void)
    5366              : {
    5367           22 :   gfc_omp_clauses *c;
    5368           22 :   locus loc = gfc_current_locus;
    5369           22 :   if ((gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_ASSUMPTIONS))
    5370              :        != MATCH_YES)
    5371           22 :       || (omp_verify_merge_absent_contains (ST_OMP_ASSUME, c->assume, NULL,
    5372              :                                             &loc) != MATCH_YES))
    5373            6 :     return MATCH_ERROR;
    5374           16 :   new_st.op = EXEC_OMP_ASSUME;
    5375           16 :   new_st.ext.omp_clauses = c;
    5376           16 :   return MATCH_YES;
    5377              : }
    5378              : 
    5379              : 
    5380              : match
    5381           28 : gfc_match_omp_assumes (void)
    5382              : {
    5383           28 :   gfc_omp_clauses *c;
    5384           28 :   locus loc = gfc_current_locus;
    5385           28 :   if (!gfc_current_ns->proc_name
    5386           27 :       || (gfc_current_ns->proc_name->attr.flavor != FL_MODULE
    5387           23 :           && !gfc_current_ns->proc_name->attr.subroutine
    5388           10 :           && !gfc_current_ns->proc_name->attr.function))
    5389              :     {
    5390            2 :       gfc_error ("!$OMP ASSUMES at %C must be in the specification part of a "
    5391              :                  "subprogram or module");
    5392            2 :       return MATCH_ERROR;
    5393              :     }
    5394           26 :   if ((gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_ASSUMPTIONS))
    5395              :        != MATCH_YES)
    5396           50 :       || (omp_verify_merge_absent_contains (ST_OMP_ASSUMES, c->assume,
    5397           24 :                                             gfc_current_ns->omp_assumes, &loc)
    5398              :           != MATCH_YES))
    5399            5 :     return MATCH_ERROR;
    5400           21 :   if (gfc_current_ns->omp_assumes == NULL)
    5401              :     {
    5402           19 :       gfc_current_ns->omp_assumes = c->assume;
    5403           19 :       c->assume = NULL;
    5404              :     }
    5405            2 :   else if (gfc_current_ns->omp_assumes && c->assume)
    5406              :     {
    5407            2 :       gfc_current_ns->omp_assumes->no_openmp |= c->assume->no_openmp;
    5408            2 :       gfc_current_ns->omp_assumes->no_openmp_routines
    5409            2 :         |= c->assume->no_openmp_routines;
    5410            2 :       gfc_current_ns->omp_assumes->no_openmp_constructs
    5411            2 :         |= c->assume->no_openmp_constructs;
    5412            2 :       gfc_current_ns->omp_assumes->no_parallelism |= c->assume->no_parallelism;
    5413            2 :       if (gfc_current_ns->omp_assumes->holds && c->assume->holds)
    5414              :         {
    5415              :           gfc_expr_list *el = gfc_current_ns->omp_assumes->holds;
    5416            1 :           for ( ; el->next ; el = el->next)
    5417              :             ;
    5418            1 :           el->next = c->assume->holds;
    5419            1 :         }
    5420            1 :       else if (c->assume->holds)
    5421            0 :         gfc_current_ns->omp_assumes->holds = c->assume->holds;
    5422            2 :       c->assume->holds = NULL;
    5423              :     }
    5424           21 :   gfc_free_omp_clauses (c);
    5425           21 :   return MATCH_YES;
    5426              : }
    5427              : 
    5428              : 
    5429              : match
    5430          162 : gfc_match_omp_critical (void)
    5431              : {
    5432          162 :   char n[GFC_MAX_SYMBOL_LEN+1];
    5433          162 :   gfc_omp_clauses *c = NULL;
    5434              : 
    5435          162 :   if (gfc_match (" ( %n )", n) != MATCH_YES)
    5436          115 :     n[0] = '\0';
    5437              : 
    5438          162 :   if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_HINT),
    5439          162 :                              /* first = */ n[0] == '\0') != MATCH_YES)
    5440              :     return MATCH_ERROR;
    5441              : 
    5442          160 :   new_st.op = EXEC_OMP_CRITICAL;
    5443          160 :   new_st.ext.omp_clauses = c;
    5444          160 :   if (n[0])
    5445           47 :     c->critical_name = xstrdup (n);
    5446              :   return MATCH_YES;
    5447              : }
    5448              : 
    5449              : 
    5450              : match
    5451          160 : gfc_match_omp_end_critical (void)
    5452              : {
    5453          160 :   char n[GFC_MAX_SYMBOL_LEN+1];
    5454              : 
    5455          160 :   if (gfc_match (" ( %n )", n) != MATCH_YES)
    5456          113 :     n[0] = '\0';
    5457          160 :   if (gfc_match_omp_eos () != MATCH_YES)
    5458              :     {
    5459            1 :       gfc_error ("Unexpected junk after $OMP CRITICAL statement at %C");
    5460            1 :       return MATCH_ERROR;
    5461              :     }
    5462              : 
    5463          159 :   new_st.op = EXEC_OMP_END_CRITICAL;
    5464          159 :   new_st.ext.omp_name = n[0] ? xstrdup (n) : NULL;
    5465          159 :   return MATCH_YES;
    5466              : }
    5467              : 
    5468              : /* depobj(depobj) depend(dep-type:loc)|destroy|update(dep-type)
    5469              :    dep-type = in/out/inout/mutexinoutset/depobj/source/sink
    5470              :    depend: !source, !sink
    5471              :    update: !source, !sink, !depobj
    5472              :    locator = exactly one list item  .*/
    5473              : match
    5474          125 : gfc_match_omp_depobj (void)
    5475              : {
    5476          125 :   gfc_omp_clauses *c = NULL;
    5477          125 :   gfc_expr *depobj;
    5478              : 
    5479          125 :   if (gfc_match (" ( %v ) ", &depobj) != MATCH_YES)
    5480              :     {
    5481            2 :       gfc_error ("Expected %<( depobj )%> at %C");
    5482            2 :       return MATCH_ERROR;
    5483              :     }
    5484          123 :   if (gfc_match ("update ( ") == MATCH_YES)
    5485              :     {
    5486           12 :       c = gfc_get_omp_clauses ();
    5487           12 :       if (gfc_match ("inoutset )") == MATCH_YES)
    5488            2 :         c->depobj_update = OMP_DEPEND_INOUTSET;
    5489           10 :       else if (gfc_match ("inout )") == MATCH_YES)
    5490            1 :         c->depobj_update = OMP_DEPEND_INOUT;
    5491            9 :       else if (gfc_match ("in )") == MATCH_YES)
    5492            2 :         c->depobj_update = OMP_DEPEND_IN;
    5493            7 :       else if (gfc_match ("out )") == MATCH_YES)
    5494            2 :         c->depobj_update = OMP_DEPEND_OUT;
    5495            5 :       else if (gfc_match ("mutexinoutset )") == MATCH_YES)
    5496            2 :         c->depobj_update = OMP_DEPEND_MUTEXINOUTSET;
    5497              :       else
    5498              :         {
    5499            3 :           gfc_error ("Expected IN, OUT, INOUT, INOUTSET or MUTEXINOUTSET "
    5500              :                      "followed by %<)%> at %C");
    5501            3 :           goto error;
    5502              :         }
    5503              :     }
    5504          111 :   else if (gfc_match ("destroy ") == MATCH_YES)
    5505              :     {
    5506           16 :       gfc_expr *destroyobj = NULL;
    5507           16 :       c = gfc_get_omp_clauses ();
    5508           16 :       c->destroy = true;
    5509              : 
    5510           16 :       if (gfc_match (" ( %v ) ", &destroyobj) == MATCH_YES)
    5511              :         {
    5512            3 :           if (destroyobj->symtree != depobj->symtree)
    5513            2 :             gfc_warning (OPT_Wopenmp, "The same depend object should be used as"
    5514              :                          " DEPOBJ argument at %L and as DESTROY argument at %L",
    5515              :                          &depobj->where, &destroyobj->where);
    5516            3 :           gfc_free_expr (destroyobj);
    5517              :         }
    5518              :     }
    5519           95 :   else if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_DEPEND), true, false)
    5520              :            != MATCH_YES)
    5521            2 :     goto error;
    5522              : 
    5523          118 :   if (c->depobj_update == OMP_DEPEND_UNSET && !c->destroy)
    5524              :     {
    5525           93 :       if (!c->doacross_source && !c->lists[OMP_LIST_DEPEND])
    5526              :         {
    5527            1 :           gfc_error ("Expected DEPEND, UPDATE, or DESTROY clause at %C");
    5528            1 :           goto error;
    5529              :         }
    5530           92 :       if (c->lists[OMP_LIST_DEPEND]->u.depend_doacross_op == OMP_DEPEND_DEPOBJ)
    5531              :         {
    5532            1 :           gfc_error ("DEPEND clause at %L of OMP DEPOBJ construct shall not "
    5533              :                      "have dependence-type DEPOBJ",
    5534              :                      c->lists[OMP_LIST_DEPEND]
    5535              :                      ? &c->lists[OMP_LIST_DEPEND]->where : &gfc_current_locus);
    5536            1 :           goto error;
    5537              :         }
    5538           91 :       if (c->lists[OMP_LIST_DEPEND]->next)
    5539              :         {
    5540            1 :           gfc_error ("DEPEND clause at %L of OMP DEPOBJ construct shall have "
    5541              :                      "only a single locator",
    5542              :                      &c->lists[OMP_LIST_DEPEND]->next->where);
    5543            1 :           goto error;
    5544              :         }
    5545              :     }
    5546              : 
    5547          115 :   c->depobj = depobj;
    5548          115 :   new_st.op = EXEC_OMP_DEPOBJ;
    5549          115 :   new_st.ext.omp_clauses = c;
    5550          115 :   return MATCH_YES;
    5551              : 
    5552            8 : error:
    5553            8 :   gfc_free_expr (depobj);
    5554            8 :   gfc_free_omp_clauses (c);
    5555            8 :   return MATCH_ERROR;
    5556              : }
    5557              : 
    5558              : match
    5559          160 : gfc_match_omp_dispatch (void)
    5560              : {
    5561          160 :   return match_omp (EXEC_OMP_DISPATCH, OMP_DISPATCH_CLAUSES);
    5562              : }
    5563              : 
    5564              : match
    5565           57 : gfc_match_omp_distribute (void)
    5566              : {
    5567           57 :   return match_omp (EXEC_OMP_DISTRIBUTE, OMP_DISTRIBUTE_CLAUSES);
    5568              : }
    5569              : 
    5570              : 
    5571              : match
    5572           44 : gfc_match_omp_distribute_parallel_do (void)
    5573              : {
    5574           44 :   return match_omp (EXEC_OMP_DISTRIBUTE_PARALLEL_DO,
    5575           44 :                     (OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
    5576           44 :                      | OMP_DO_CLAUSES)
    5577           44 :                     & ~(omp_mask (OMP_CLAUSE_ORDERED)
    5578           44 :                         | OMP_CLAUSE_LINEAR | OMP_CLAUSE_NOWAIT));
    5579              : }
    5580              : 
    5581              : 
    5582              : match
    5583           34 : gfc_match_omp_distribute_parallel_do_simd (void)
    5584              : {
    5585           34 :   return match_omp (EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD,
    5586           34 :                     (OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
    5587           34 :                      | OMP_DO_CLAUSES | OMP_SIMD_CLAUSES)
    5588           34 :                     & ~(omp_mask (OMP_CLAUSE_ORDERED) | OMP_CLAUSE_NOWAIT));
    5589              : }
    5590              : 
    5591              : 
    5592              : match
    5593           52 : gfc_match_omp_distribute_simd (void)
    5594              : {
    5595           52 :   return match_omp (EXEC_OMP_DISTRIBUTE_SIMD,
    5596           52 :                     OMP_DISTRIBUTE_CLAUSES | OMP_SIMD_CLAUSES);
    5597              : }
    5598              : 
    5599              : 
    5600              : match
    5601         1252 : gfc_match_omp_do (void)
    5602              : {
    5603         1252 :   return match_omp (EXEC_OMP_DO, OMP_DO_CLAUSES);
    5604              : }
    5605              : 
    5606              : 
    5607              : match
    5608          137 : gfc_match_omp_do_simd (void)
    5609              : {
    5610          137 :   return match_omp (EXEC_OMP_DO_SIMD, OMP_DO_CLAUSES | OMP_SIMD_CLAUSES);
    5611              : }
    5612              : 
    5613              : 
    5614              : match
    5615           70 : gfc_match_omp_loop (void)
    5616              : {
    5617           70 :   return match_omp (EXEC_OMP_LOOP, OMP_LOOP_CLAUSES);
    5618              : }
    5619              : 
    5620              : 
    5621              : match
    5622           35 : gfc_match_omp_teams_loop (void)
    5623              : {
    5624           35 :   return match_omp (EXEC_OMP_TEAMS_LOOP, OMP_TEAMS_CLAUSES | OMP_LOOP_CLAUSES);
    5625              : }
    5626              : 
    5627              : 
    5628              : match
    5629           18 : gfc_match_omp_target_teams_loop (void)
    5630              : {
    5631           18 :   return match_omp (EXEC_OMP_TARGET_TEAMS_LOOP,
    5632           18 :                     OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES | OMP_LOOP_CLAUSES);
    5633              : }
    5634              : 
    5635              : 
    5636              : match
    5637           31 : gfc_match_omp_parallel_loop (void)
    5638              : {
    5639           31 :   return match_omp (EXEC_OMP_PARALLEL_LOOP,
    5640           31 :                     OMP_PARALLEL_CLAUSES | OMP_LOOP_CLAUSES);
    5641              : }
    5642              : 
    5643              : 
    5644              : match
    5645           16 : gfc_match_omp_target_parallel_loop (void)
    5646              : {
    5647           16 :   return match_omp (EXEC_OMP_TARGET_PARALLEL_LOOP,
    5648           16 :                     (OMP_TARGET_CLAUSES | OMP_PARALLEL_CLAUSES
    5649           16 :                      | OMP_LOOP_CLAUSES));
    5650              : }
    5651              : 
    5652              : 
    5653              : match
    5654          101 : gfc_match_omp_error (void)
    5655              : {
    5656          101 :   locus loc = gfc_current_locus;
    5657          101 :   match m = match_omp (EXEC_OMP_ERROR, OMP_ERROR_CLAUSES);
    5658          101 :   if (m != MATCH_YES)
    5659              :     return m;
    5660              : 
    5661           82 :   gfc_omp_clauses *c = new_st.ext.omp_clauses;
    5662           82 :   if (c->severity == OMP_SEVERITY_UNSET)
    5663           45 :     c->severity = OMP_SEVERITY_FATAL;
    5664           82 :   if (new_st.ext.omp_clauses->at == OMP_AT_EXECUTION)
    5665              :     return MATCH_YES;
    5666           37 :   if (c->message
    5667           37 :       && (!gfc_resolve_expr (c->message)
    5668           16 :           || c->message->ts.type != BT_CHARACTER
    5669           14 :           || c->message->ts.kind != gfc_default_character_kind
    5670           13 :           || c->message->rank != 0))
    5671              :     {
    5672            4 :       gfc_error ("MESSAGE clause at %L requires a scalar default-kind "
    5673              :                    "CHARACTER expression",
    5674            4 :                  &new_st.ext.omp_clauses->message->where);
    5675            4 :       return MATCH_ERROR;
    5676              :     }
    5677           33 :   if (c->message && !gfc_is_constant_expr (c->message))
    5678              :     {
    5679            2 :       gfc_error ("Constant character expression required in MESSAGE clause "
    5680            2 :                  "at %L", &new_st.ext.omp_clauses->message->where);
    5681            2 :       return MATCH_ERROR;
    5682              :     }
    5683           31 :   if (c->message)
    5684              :     {
    5685           10 :       const char *msg = G_("$OMP ERROR encountered at %L: %s");
    5686           10 :       gcc_assert (c->message->expr_type == EXPR_CONSTANT);
    5687           10 :       gfc_charlen_t slen = c->message->value.character.length;
    5688           10 :       int i = gfc_validate_kind (BT_CHARACTER, gfc_default_character_kind,
    5689              :                                  false);
    5690           10 :       size_t size = slen * gfc_character_kinds[i].bit_size / 8;
    5691           10 :       unsigned char *s = XCNEWVAR (unsigned char, size + 1);
    5692           10 :       gfc_encode_character (gfc_default_character_kind, slen,
    5693           10 :                             c->message->value.character.string,
    5694              :                             (unsigned char *) s, size);
    5695           10 :       s[size] = '\0';
    5696           10 :       if (c->severity == OMP_SEVERITY_WARNING)
    5697            6 :         gfc_warning_now (0, msg, &loc, s);
    5698              :       else
    5699            4 :         gfc_error_now (msg, &loc, s);
    5700           10 :       free (s);
    5701              :     }
    5702              :   else
    5703              :     {
    5704           21 :       const char *msg = G_("$OMP ERROR encountered at %L");
    5705           21 :       if (c->severity == OMP_SEVERITY_WARNING)
    5706            7 :         gfc_warning_now (0, msg, &loc);
    5707              :       else
    5708           14 :         gfc_error_now (msg, &loc);
    5709              :     }
    5710              :   return MATCH_YES;
    5711              : }
    5712              : 
    5713              : match
    5714           86 : gfc_match_omp_flush (void)
    5715              : {
    5716           86 :   gfc_omp_namelist *list = NULL;
    5717           86 :   gfc_omp_clauses *c = NULL;
    5718           86 :   gfc_gobble_whitespace ();
    5719           86 :   enum gfc_omp_memorder mo = OMP_MEMORDER_UNSET;
    5720           86 :   if (gfc_match_omp_eos () == MATCH_NO && gfc_peek_ascii_char () != '(')
    5721              :     {
    5722           14 :       if (gfc_match ("seq_cst") == MATCH_YES)
    5723              :         mo = OMP_MEMORDER_SEQ_CST;
    5724           11 :       else if (gfc_match ("acq_rel") == MATCH_YES)
    5725              :         mo = OMP_MEMORDER_ACQ_REL;
    5726            8 :       else if (gfc_match ("release") == MATCH_YES)
    5727              :         mo = OMP_MEMORDER_RELEASE;
    5728            5 :       else if (gfc_match ("acquire") == MATCH_YES)
    5729              :         mo = OMP_MEMORDER_ACQUIRE;
    5730              :       else
    5731              :         {
    5732            2 :           gfc_error ("Expected SEQ_CST, AQC_REL, RELEASE, or ACQUIRE at %C");
    5733            2 :           return MATCH_ERROR;
    5734              :         }
    5735           12 :       c = gfc_get_omp_clauses ();
    5736           12 :       c->memorder = mo;
    5737              :     }
    5738           84 :   gfc_match_omp_variable_list (" (", &list, true);
    5739           84 :   if (list && mo != OMP_MEMORDER_UNSET)
    5740              :     {
    5741            4 :       gfc_error ("List specified together with memory order clause in FLUSH "
    5742              :                  "directive at %C");
    5743            4 :       gfc_free_omp_namelist (list, false, false, false, false);
    5744            4 :       gfc_free_omp_clauses (c);
    5745            4 :       return MATCH_ERROR;
    5746              :     }
    5747           80 :   if (gfc_match_omp_eos () != MATCH_YES)
    5748              :     {
    5749            0 :       gfc_error ("Unexpected junk after $OMP FLUSH statement at %C");
    5750            0 :       gfc_free_omp_namelist (list, false, false, false, false);
    5751            0 :       gfc_free_omp_clauses (c);
    5752            0 :       return MATCH_ERROR;
    5753              :     }
    5754           80 :   new_st.op = EXEC_OMP_FLUSH;
    5755           80 :   new_st.ext.omp_namelist = list;
    5756           80 :   new_st.ext.omp_clauses = c;
    5757           80 :   return MATCH_YES;
    5758              : }
    5759              : 
    5760              : 
    5761              : match
    5762          188 : gfc_match_omp_declare_simd (void)
    5763              : {
    5764          188 :   locus where = gfc_current_locus;
    5765          188 :   gfc_symbol *proc_name;
    5766          188 :   gfc_omp_clauses *c;
    5767          188 :   gfc_omp_declare_simd *ods;
    5768          188 :   bool needs_space = false;
    5769              : 
    5770          188 :   switch (gfc_match (" ( "))
    5771              :     {
    5772          144 :     case MATCH_YES:
    5773          144 :       if (gfc_match_symbol (&proc_name, /* host assoc = */ true) != MATCH_YES
    5774          144 :           || gfc_match (" ) ") != MATCH_YES)
    5775            0 :         return MATCH_ERROR;
    5776              :       break;
    5777           44 :     case MATCH_NO: proc_name = NULL; needs_space = true; break;
    5778              :     case MATCH_ERROR: return MATCH_ERROR;
    5779              :     }
    5780              : 
    5781          188 :   if (gfc_match_omp_clauses (&c, OMP_DECLARE_SIMD_CLAUSES, true,
    5782              :                              needs_space) != MATCH_YES)
    5783              :     return MATCH_ERROR;
    5784              : 
    5785          183 :   if (gfc_current_ns->is_block_data)
    5786              :     {
    5787            1 :       gfc_free_omp_clauses (c);
    5788            1 :       return MATCH_YES;
    5789              :     }
    5790              : 
    5791          182 :   ods = gfc_get_omp_declare_simd ();
    5792          182 :   ods->where = where;
    5793          182 :   ods->proc_name = proc_name;
    5794          182 :   ods->clauses = c;
    5795          182 :   ods->next = gfc_current_ns->omp_declare_simd;
    5796          182 :   gfc_current_ns->omp_declare_simd = ods;
    5797          182 :   return MATCH_YES;
    5798              : }
    5799              : 
    5800              : 
    5801              : static bool
    5802          877 : match_udr_expr (gfc_symtree *omp_sym1, gfc_symtree *omp_sym2)
    5803              : {
    5804          877 :   match m;
    5805          877 :   locus old_loc = gfc_current_locus;
    5806          877 :   char sname[GFC_MAX_SYMBOL_LEN + 1];
    5807          877 :   gfc_symbol *sym;
    5808          877 :   gfc_namespace *ns = gfc_current_ns;
    5809          877 :   gfc_expr *lvalue = NULL, *rvalue = NULL;
    5810          877 :   gfc_symtree *st;
    5811          877 :   gfc_actual_arglist *arglist;
    5812              : 
    5813          877 :   m = gfc_match (" %v =", &lvalue);
    5814          877 :   if (m != MATCH_YES)
    5815          200 :     gfc_current_locus = old_loc;
    5816              :   else
    5817              :     {
    5818          677 :       m = gfc_match (" %e )", &rvalue);
    5819          677 :       if (m == MATCH_YES)
    5820              :         {
    5821          675 :           ns->code = gfc_get_code (EXEC_ASSIGN);
    5822          675 :           ns->code->expr1 = lvalue;
    5823          675 :           ns->code->expr2 = rvalue;
    5824          675 :           ns->code->loc = old_loc;
    5825          675 :           return true;
    5826              :         }
    5827              : 
    5828            2 :       gfc_current_locus = old_loc;
    5829            2 :       gfc_free_expr (lvalue);
    5830              :     }
    5831              : 
    5832          202 :   m = gfc_match (" %n", sname);
    5833          202 :   if (m != MATCH_YES)
    5834              :     return false;
    5835              : 
    5836          202 :   if (strcmp (sname, omp_sym1->name) == 0
    5837          200 :       || strcmp (sname, omp_sym2->name) == 0)
    5838              :     return false;
    5839              : 
    5840          200 :   gfc_current_ns = ns->parent;
    5841          200 :   if (gfc_get_ha_sym_tree (sname, &st))
    5842              :     return false;
    5843              : 
    5844          200 :   sym = st->n.sym;
    5845          200 :   if (sym->attr.flavor != FL_PROCEDURE
    5846           72 :       && sym->attr.flavor != FL_UNKNOWN)
    5847              :     return false;
    5848              : 
    5849          199 :   if (!sym->attr.generic
    5850          189 :       && !sym->attr.subroutine
    5851           71 :       && !sym->attr.function)
    5852              :     {
    5853           71 :       if (!(sym->attr.external && !sym->attr.referenced))
    5854              :         {
    5855              :           /* ...create a symbol in this scope...  */
    5856           71 :           if (sym->ns != gfc_current_ns
    5857           71 :               && gfc_get_sym_tree (sname, NULL, &st, false) == 1)
    5858              :             return false;
    5859              : 
    5860           71 :           if (sym != st->n.sym)
    5861           71 :             sym = st->n.sym;
    5862              :         }
    5863              : 
    5864              :       /* ...and then to try to make the symbol into a subroutine.  */
    5865           71 :       if (!gfc_add_subroutine (&sym->attr, sym->name, NULL))
    5866              :         return false;
    5867              :     }
    5868              : 
    5869          199 :   gfc_set_sym_referenced (sym);
    5870          199 :   gfc_gobble_whitespace ();
    5871          199 :   if (gfc_peek_ascii_char () != '(')
    5872              :     return false;
    5873              : 
    5874          195 :   gfc_current_ns = ns;
    5875          195 :   m = gfc_match_actual_arglist (1, &arglist);
    5876          195 :   if (m != MATCH_YES)
    5877              :     return false;
    5878              : 
    5879          195 :   if (gfc_match_char (')') != MATCH_YES)
    5880              :     return false;
    5881              : 
    5882          195 :   ns->code = gfc_get_code (EXEC_CALL);
    5883          195 :   ns->code->symtree = st;
    5884          195 :   ns->code->ext.actual = arglist;
    5885          195 :   ns->code->loc = old_loc;
    5886          195 :   return true;
    5887              : }
    5888              : 
    5889              : static bool
    5890         1156 : gfc_omp_udr_predef (gfc_omp_reduction_op rop, const char *name,
    5891              :                     gfc_typespec *ts, const char **n)
    5892              : {
    5893         1156 :   if (!gfc_numeric_ts (ts) && ts->type != BT_LOGICAL)
    5894              :     return false;
    5895              : 
    5896          648 :   switch (rop)
    5897              :     {
    5898           21 :     case OMP_REDUCTION_PLUS:
    5899           21 :     case OMP_REDUCTION_MINUS:
    5900           21 :     case OMP_REDUCTION_TIMES:
    5901           21 :       return ts->type != BT_LOGICAL;
    5902            8 :     case OMP_REDUCTION_AND:
    5903            8 :     case OMP_REDUCTION_OR:
    5904            8 :     case OMP_REDUCTION_EQV:
    5905            8 :     case OMP_REDUCTION_NEQV:
    5906            8 :       return ts->type == BT_LOGICAL;
    5907          618 :     case OMP_REDUCTION_USER:
    5908          618 :       if (name[0] != '.' && (ts->type == BT_INTEGER || ts->type == BT_REAL))
    5909              :         {
    5910          546 :           gfc_symbol *sym;
    5911              : 
    5912          546 :           gfc_find_symbol (name, NULL, 1, &sym);
    5913          546 :           if (sym != NULL)
    5914              :             {
    5915           93 :               if (sym->attr.intrinsic)
    5916            0 :                 *n = sym->name;
    5917           93 :               else if ((sym->attr.flavor != FL_UNKNOWN
    5918           81 :                         && sym->attr.flavor != FL_PROCEDURE)
    5919           69 :                        || sym->attr.external
    5920           54 :                        || sym->attr.generic
    5921           54 :                        || sym->attr.entry
    5922           54 :                        || sym->attr.result
    5923           54 :                        || sym->attr.dummy
    5924           54 :                        || sym->attr.subroutine
    5925           50 :                        || sym->attr.pointer
    5926           50 :                        || sym->attr.target
    5927           50 :                        || sym->attr.cray_pointer
    5928           50 :                        || sym->attr.cray_pointee
    5929           50 :                        || (sym->attr.proc != PROC_UNKNOWN
    5930            0 :                            && sym->attr.proc != PROC_INTRINSIC)
    5931           50 :                        || sym->attr.if_source != IFSRC_UNKNOWN
    5932           50 :                        || sym == sym->ns->proc_name)
    5933           43 :                 *n = NULL;
    5934              :               else
    5935           50 :                 *n = sym->name;
    5936              :             }
    5937              :           else
    5938          453 :             *n = name;
    5939          546 :           if (*n
    5940          503 :               && (strcmp (*n, "max") == 0 || strcmp (*n, "min") == 0))
    5941           54 :             return true;
    5942          510 :           else if (*n
    5943          467 :                    && ts->type == BT_INTEGER
    5944          383 :                    && (strcmp (*n, "iand") == 0
    5945          377 :                        || strcmp (*n, "ior") == 0
    5946          371 :                        || strcmp (*n, "ieor") == 0))
    5947              :             return true;
    5948              :         }
    5949              :       break;
    5950              :     default:
    5951              :       break;
    5952              :     }
    5953              :   return false;
    5954              : }
    5955              : 
    5956              : gfc_omp_udr *
    5957          639 : gfc_omp_udr_find (gfc_symtree *st, gfc_typespec *ts)
    5958              : {
    5959          639 :   gfc_omp_udr *omp_udr;
    5960              : 
    5961          639 :   if (st == NULL)
    5962              :     return NULL;
    5963              : 
    5964          250 :   for (omp_udr = st->n.omp_udr; omp_udr; omp_udr = omp_udr->next)
    5965          154 :     if (omp_udr->ts.type == ts->type
    5966           89 :         || ((omp_udr->ts.type == BT_DERIVED || omp_udr->ts.type == BT_CLASS)
    5967            0 :             && (ts->type == BT_DERIVED || ts->type == BT_CLASS)))
    5968              :       {
    5969           65 :         if (omp_udr->ts.type == BT_DERIVED || omp_udr->ts.type == BT_CLASS)
    5970              :           {
    5971           12 :             if (strcmp (omp_udr->ts.u.derived->name, ts->u.derived->name) == 0)
    5972              :               return omp_udr;
    5973              :           }
    5974           53 :         else if (omp_udr->ts.kind == ts->kind)
    5975              :           {
    5976           19 :             if (omp_udr->ts.type == BT_CHARACTER)
    5977              :               {
    5978           17 :                 if (omp_udr->ts.u.cl->length == NULL
    5979           15 :                     || ts->u.cl->length == NULL)
    5980              :                   return omp_udr;
    5981           15 :                 if (omp_udr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
    5982              :                   return omp_udr;
    5983           15 :                 if (ts->u.cl->length->expr_type != EXPR_CONSTANT)
    5984              :                   return omp_udr;
    5985           15 :                 if (omp_udr->ts.u.cl->length->ts.type != BT_INTEGER)
    5986              :                   return omp_udr;
    5987           15 :                 if (ts->u.cl->length->ts.type != BT_INTEGER)
    5988              :                   return omp_udr;
    5989           15 :                 if (gfc_compare_expr (omp_udr->ts.u.cl->length,
    5990              :                                       ts->u.cl->length, INTRINSIC_EQ) != 0)
    5991           15 :                   continue;
    5992              :               }
    5993            2 :             return omp_udr;
    5994              :           }
    5995              :       }
    5996              :   return NULL;
    5997              : }
    5998              : 
    5999              : match
    6000          532 : gfc_match_omp_declare_reduction (void)
    6001              : {
    6002          532 :   match m;
    6003          532 :   gfc_intrinsic_op op;
    6004          532 :   char name[GFC_MAX_SYMBOL_LEN + 3];
    6005          532 :   auto_vec<gfc_typespec, 5> tss;
    6006          532 :   gfc_typespec ts;
    6007          532 :   unsigned int i;
    6008          532 :   gfc_symtree *st;
    6009          532 :   locus where = gfc_current_locus;
    6010          532 :   locus end_loc = gfc_current_locus;
    6011          532 :   bool end_loc_set = false;
    6012          532 :   gfc_omp_reduction_op rop = OMP_REDUCTION_NONE;
    6013              : 
    6014          532 :   if (gfc_match_char ('(') != MATCH_YES)
    6015              :     return MATCH_ERROR;
    6016              : 
    6017          530 :   m = gfc_match (" %o : ", &op);
    6018          530 :   if (m == MATCH_ERROR)
    6019              :     return MATCH_ERROR;
    6020          530 :   if (m == MATCH_YES)
    6021              :     {
    6022          117 :       snprintf (name, sizeof name, "operator %s", gfc_op2string (op));
    6023          117 :       rop = (gfc_omp_reduction_op) op;
    6024              :     }
    6025              :   else
    6026              :     {
    6027          413 :       m = gfc_match_defined_op_name (name + 1, 1);
    6028          413 :       if (m == MATCH_ERROR)
    6029              :         return MATCH_ERROR;
    6030          413 :       if (m == MATCH_YES)
    6031              :         {
    6032           41 :           name[0] = '.';
    6033           41 :           strcat (name, ".");
    6034           41 :           if (gfc_match (" : ") != MATCH_YES)
    6035              :             return MATCH_ERROR;
    6036              :         }
    6037              :       else
    6038              :         {
    6039          372 :           if (gfc_match (" %n : ", name) != MATCH_YES)
    6040              :             return MATCH_ERROR;
    6041              :         }
    6042              :       rop = OMP_REDUCTION_USER;
    6043              :     }
    6044              : 
    6045          529 :   m = gfc_match_type_spec (&ts);
    6046          529 :   if (m != MATCH_YES)
    6047              :     return MATCH_ERROR;
    6048              :   /* Treat len=: the same as len=*.  */
    6049          528 :   if (ts.type == BT_CHARACTER)
    6050           61 :     ts.deferred = false;
    6051          528 :   tss.safe_push (ts);
    6052              : 
    6053         1093 :   while (gfc_match_char (',') == MATCH_YES)
    6054              :     {
    6055           37 :       m = gfc_match_type_spec (&ts);
    6056           37 :       if (m != MATCH_YES)
    6057              :         return MATCH_ERROR;
    6058           37 :       tss.safe_push (ts);
    6059              :     }
    6060          528 :   if (gfc_match_char (':') != MATCH_YES)
    6061              :     return MATCH_ERROR;
    6062              : 
    6063          527 :   st = gfc_find_symtree (gfc_current_ns->omp_udr_root, name);
    6064         1084 :   for (i = 0; i < tss.length (); i++)
    6065              :     {
    6066          564 :       gfc_symtree *omp_out, *omp_in;
    6067          564 :       gfc_symtree *omp_priv = NULL, *omp_orig = NULL;
    6068          564 :       gfc_namespace *combiner_ns, *initializer_ns = NULL;
    6069          564 :       gfc_omp_udr *prev_udr, *omp_udr;
    6070          564 :       const char *predef_name = NULL;
    6071              : 
    6072          564 :       omp_udr = gfc_get_omp_udr ();
    6073          564 :       omp_udr->name = gfc_get_string ("%s", name);
    6074          564 :       omp_udr->rop = rop;
    6075          564 :       omp_udr->ts = tss[i];
    6076          564 :       omp_udr->where = where;
    6077              : 
    6078          564 :       gfc_current_ns = combiner_ns = gfc_get_namespace (gfc_current_ns, 1);
    6079          564 :       combiner_ns->proc_name = combiner_ns->parent->proc_name;
    6080              : 
    6081          564 :       gfc_get_sym_tree ("omp_out", combiner_ns, &omp_out, false);
    6082          564 :       gfc_get_sym_tree ("omp_in", combiner_ns, &omp_in, false);
    6083          564 :       combiner_ns->omp_udr_ns = 1;
    6084          564 :       omp_out->n.sym->ts = tss[i];
    6085          564 :       omp_in->n.sym->ts = tss[i];
    6086          564 :       omp_out->n.sym->attr.omp_udr_artificial_var = 1;
    6087          564 :       omp_in->n.sym->attr.omp_udr_artificial_var = 1;
    6088          564 :       omp_out->n.sym->attr.flavor = FL_VARIABLE;
    6089          564 :       omp_in->n.sym->attr.flavor = FL_VARIABLE;
    6090          564 :       gfc_commit_symbols ();
    6091          564 :       omp_udr->combiner_ns = combiner_ns;
    6092          564 :       omp_udr->omp_out = omp_out->n.sym;
    6093          564 :       omp_udr->omp_in = omp_in->n.sym;
    6094              : 
    6095          564 :       locus old_loc = gfc_current_locus;
    6096              : 
    6097          564 :       if (!match_udr_expr (omp_out, omp_in))
    6098              :         {
    6099            4 :          syntax:
    6100            7 :           gfc_current_locus = old_loc;
    6101            7 :           gfc_current_ns = combiner_ns->parent;
    6102            7 :           gfc_undo_symbols ();
    6103            7 :           gfc_free_omp_udr (omp_udr);
    6104            7 :           return MATCH_ERROR;
    6105              :         }
    6106              : 
    6107          560 :       if (gfc_match (" initializer ( ") == MATCH_YES)
    6108              :         {
    6109          313 :           gfc_current_ns = combiner_ns->parent;
    6110          313 :           initializer_ns = gfc_get_namespace (gfc_current_ns, 1);
    6111          313 :           gfc_current_ns = initializer_ns;
    6112          313 :           initializer_ns->proc_name = initializer_ns->parent->proc_name;
    6113              : 
    6114          313 :           gfc_get_sym_tree ("omp_priv", initializer_ns, &omp_priv, false);
    6115          313 :           gfc_get_sym_tree ("omp_orig", initializer_ns, &omp_orig, false);
    6116          313 :           initializer_ns->omp_udr_ns = 1;
    6117          313 :           omp_priv->n.sym->ts = tss[i];
    6118          313 :           omp_orig->n.sym->ts = tss[i];
    6119          313 :           omp_priv->n.sym->attr.omp_udr_artificial_var = 1;
    6120          313 :           omp_orig->n.sym->attr.omp_udr_artificial_var = 1;
    6121          313 :           omp_priv->n.sym->attr.flavor = FL_VARIABLE;
    6122          313 :           omp_orig->n.sym->attr.flavor = FL_VARIABLE;
    6123          313 :           gfc_commit_symbols ();
    6124          313 :           omp_udr->initializer_ns = initializer_ns;
    6125          313 :           omp_udr->omp_priv = omp_priv->n.sym;
    6126          313 :           omp_udr->omp_orig = omp_orig->n.sym;
    6127              : 
    6128          313 :           if (!match_udr_expr (omp_priv, omp_orig))
    6129            3 :             goto syntax;
    6130              :         }
    6131              : 
    6132          557 :       gfc_current_ns = combiner_ns->parent;
    6133          557 :       if (!end_loc_set)
    6134              :         {
    6135          520 :           end_loc_set = true;
    6136          520 :           end_loc = gfc_current_locus;
    6137              :         }
    6138          557 :       gfc_current_locus = old_loc;
    6139              : 
    6140          557 :       prev_udr = gfc_omp_udr_find (st, &tss[i]);
    6141          557 :       if (gfc_omp_udr_predef (rop, name, &tss[i], &predef_name)
    6142              :           /* Don't error on !$omp declare reduction (min : integer : ...)
    6143              :              just yet, there could be integer :: min afterwards,
    6144              :              making it valid.  When the UDR is resolved, we'll get
    6145              :              to it again.  */
    6146          557 :           && (rop != OMP_REDUCTION_USER || name[0] == '.'))
    6147              :         {
    6148           29 :           if (predef_name)
    6149            0 :             gfc_error_now ("Redefinition of predefined %s "
    6150              :                            "!$OMP DECLARE REDUCTION at %L",
    6151              :                            predef_name, &where);
    6152              :           else
    6153           29 :             gfc_error_now ("Redefinition of predefined "
    6154              :                            "!$OMP DECLARE REDUCTION at %L", &where);
    6155              :         }
    6156          528 :       else if (prev_udr)
    6157              :         {
    6158            6 :           gfc_error_now ("Redefinition of !$OMP DECLARE REDUCTION at %L",
    6159              :                          &where);
    6160            6 :           gfc_error_now ("Previous !$OMP DECLARE REDUCTION at %L",
    6161              :                          &prev_udr->where);
    6162              :         }
    6163          522 :       else if (st)
    6164              :         {
    6165           96 :           omp_udr->next = st->n.omp_udr;
    6166           96 :           st->n.omp_udr = omp_udr;
    6167              :         }
    6168              :       else
    6169              :         {
    6170          426 :           st = gfc_new_symtree (&gfc_current_ns->omp_udr_root, name);
    6171          426 :           st->n.omp_udr = omp_udr;
    6172              :         }
    6173              :     }
    6174              : 
    6175          520 :   if (end_loc_set)
    6176              :     {
    6177          520 :       gfc_current_locus = end_loc;
    6178          520 :       if (gfc_match_omp_eos () != MATCH_YES)
    6179              :         {
    6180            1 :           gfc_error ("Unexpected junk after !$OMP DECLARE REDUCTION at %C");
    6181            1 :           gfc_current_locus = where;
    6182            1 :           return MATCH_ERROR;
    6183              :         }
    6184              : 
    6185              :       return MATCH_YES;
    6186              :     }
    6187            0 :   gfc_clear_error ();
    6188            0 :   return MATCH_ERROR;
    6189          532 : }
    6190              : 
    6191              : 
    6192              : match
    6193          469 : gfc_match_omp_declare_target (void)
    6194              : {
    6195          469 :   locus old_loc;
    6196          469 :   match m;
    6197          469 :   gfc_omp_clauses *c = NULL;
    6198          469 :   int list;
    6199          469 :   gfc_omp_namelist *n;
    6200          469 :   gfc_symbol *s;
    6201              : 
    6202          469 :   old_loc = gfc_current_locus;
    6203              : 
    6204          469 :   if (gfc_current_ns->proc_name
    6205          469 :       && gfc_match_omp_eos () == MATCH_YES)
    6206              :     {
    6207          138 :       if (!gfc_add_omp_declare_target (&gfc_current_ns->proc_name->attr,
    6208          138 :                                        gfc_current_ns->proc_name->name,
    6209              :                                        &old_loc))
    6210            0 :         goto cleanup;
    6211              :       return MATCH_YES;
    6212              :     }
    6213              : 
    6214          331 :   if (gfc_current_ns->proc_name
    6215          331 :       && gfc_current_ns->proc_name->attr.if_source == IFSRC_IFBODY)
    6216              :     {
    6217            2 :       gfc_error ("Only the !$OMP DECLARE TARGET form without "
    6218              :                  "clauses is allowed in interface block at %C");
    6219            2 :       goto cleanup;
    6220              :     }
    6221              : 
    6222          329 :   m = gfc_match (" (");
    6223          329 :   if (m == MATCH_YES)
    6224              :     {
    6225           83 :       c = gfc_get_omp_clauses ();
    6226           83 :       gfc_current_locus = old_loc;
    6227           83 :       m = gfc_match_omp_to_link (" (", &c->lists[OMP_LIST_ENTER]);
    6228           83 :       if (m != MATCH_YES)
    6229            0 :         goto syntax;
    6230           83 :       if (gfc_match_omp_eos () != MATCH_YES)
    6231              :         {
    6232            0 :           gfc_error ("Unexpected junk after !$OMP DECLARE TARGET at %C");
    6233            0 :           goto cleanup;
    6234              :         }
    6235              :     }
    6236          246 :   else if (gfc_match_omp_clauses (&c, OMP_DECLARE_TARGET_CLAUSES) != MATCH_YES)
    6237              :     return MATCH_ERROR;
    6238              : 
    6239          323 :   gfc_buffer_error (false);
    6240              : 
    6241          323 :   static const int to_enter_link_lists[]
    6242              :     = { OMP_LIST_TO, OMP_LIST_ENTER, OMP_LIST_LINK, OMP_LIST_LOCAL };
    6243         1615 :   for (size_t listn = 0; listn < ARRAY_SIZE (to_enter_link_lists)
    6244         1615 :                          && (list = to_enter_link_lists[listn], true); ++listn)
    6245         1832 :     for (n = c->lists[list]; n; n = n->next)
    6246          540 :       if (n->sym)
    6247          499 :         n->sym->mark = 0;
    6248           41 :       else if (n->u.common->head)
    6249           41 :         n->u.common->head->mark = 0;
    6250              : 
    6251          323 :   if (c->device_type == OMP_DEVICE_TYPE_UNSET)
    6252          255 :     c->device_type = OMP_DEVICE_TYPE_ANY;
    6253         1292 :   for (size_t listn = 0; listn < ARRAY_SIZE (to_enter_link_lists)
    6254         1615 :                          && (list = to_enter_link_lists[listn], true); ++listn)
    6255         1832 :     for (n = c->lists[list]; n; n = n->next)
    6256          540 :       if (n->sym)
    6257              :         {
    6258          499 :           if (n->sym->attr.in_common)
    6259            1 :             gfc_error_now ("OMP DECLARE TARGET variable at %L is an "
    6260              :                            "element of a COMMON block", &n->where);
    6261          498 :           else if (n->sym->attr.omp_groupprivate && list != OMP_LIST_LOCAL)
    6262           12 :             gfc_error_now ("List item %qs at %L not appear in the %qs clause "
    6263              :                            "as it was previously specified in a GROUPPRIVATE "
    6264              :                            "directive", n->sym->name, &n->where,
    6265              :                            list == OMP_LIST_LINK
    6266            5 :                            ? "link" : list == OMP_LIST_TO ? "to" : "enter");
    6267          491 :           else if (n->sym->mark)
    6268            9 :             gfc_error_now ("Variable at %L mentioned multiple times in "
    6269              :                            "clauses of the same OMP DECLARE TARGET directive",
    6270              :                            &n->where);
    6271          482 :           else if ((n->sym->attr.omp_declare_target_link
    6272          477 :                     || n->sym->attr.omp_declare_target_local)
    6273              :                    && list != OMP_LIST_LINK
    6274            7 :                    && list != OMP_LIST_LOCAL)
    6275            1 :             gfc_error_now ("OMP DECLARE TARGET variable at %L previously "
    6276              :                            "mentioned in %s clause and later in %s clause",
    6277              :                            &n->where,
    6278              :                            n->sym->attr.omp_declare_target_link ? "LINK"
    6279              :                                                                 : "LOCAL",
    6280              :                            list == OMP_LIST_TO ? "TO" : "ENTER");
    6281          481 :           else if (n->sym->attr.omp_declare_target
    6282           14 :                    && (list == OMP_LIST_LINK || list == OMP_LIST_LOCAL))
    6283            1 :             gfc_error_now ("OMP DECLARE TARGET variable at %L previously "
    6284              :                            "mentioned in TO or ENTER clause and later in "
    6285              :                            "%s clause", &n->where,
    6286              :                            list == OMP_LIST_LINK ? "LINK" : "LOCAL");
    6287              :           else
    6288              :             {
    6289          480 :               if (list == OMP_LIST_TO || list == OMP_LIST_ENTER)
    6290          441 :                 gfc_add_omp_declare_target (&n->sym->attr, n->sym->name,
    6291              :                                             &n->sym->declared_at);
    6292          480 :               if (list == OMP_LIST_LINK)
    6293           30 :                 gfc_add_omp_declare_target_link (&n->sym->attr, n->sym->name,
    6294           30 :                                                  &n->sym->declared_at);
    6295          480 :               if (list == OMP_LIST_LOCAL)
    6296            9 :                 gfc_add_omp_declare_target_local (&n->sym->attr, n->sym->name,
    6297            9 :                                                   &n->sym->declared_at);
    6298              :             }
    6299          499 :           if (n->sym->attr.omp_device_type != OMP_DEVICE_TYPE_UNSET
    6300           36 :               && n->sym->attr.omp_device_type != c->device_type)
    6301              :             {
    6302           12 :               const char *dt = "any";
    6303           12 :               if (n->sym->attr.omp_device_type == OMP_DEVICE_TYPE_NOHOST)
    6304              :                 dt = "nohost";
    6305            8 :               else if (n->sym->attr.omp_device_type == OMP_DEVICE_TYPE_HOST)
    6306            4 :                 dt = "host";
    6307           12 :               if (n->sym->attr.omp_groupprivate)
    6308            1 :                 gfc_error_now ("List item %qs at %L set in previous OMP "
    6309              :                                "GROUPPRIVATE directive to the different "
    6310              :                                "DEVICE_TYPE %qs", n->sym->name, &n->where, dt);
    6311              :               else
    6312           11 :                 gfc_error_now ("List item %qs at %L set in previous OMP "
    6313              :                                "DECLARE TARGET directive to the different "
    6314              :                                "DEVICE_TYPE %qs", n->sym->name, &n->where, dt);
    6315              :             }
    6316          499 :           n->sym->attr.omp_device_type = c->device_type;
    6317          499 :           if (c->indirect && c->device_type != OMP_DEVICE_TYPE_ANY)
    6318              :             {
    6319            1 :               gfc_error_now ("DEVICE_TYPE must be ANY when used with INDIRECT "
    6320              :                              "at %L", &n->where);
    6321            1 :               c->indirect = 0;
    6322              :             }
    6323          499 :           n->sym->attr.omp_declare_target_indirect = c->indirect;
    6324          499 :           if (list == OMP_LIST_LINK && c->device_type == OMP_DEVICE_TYPE_NOHOST)
    6325            3 :             gfc_error_now ("List item %qs at %L set with NOHOST specified may "
    6326              :                            "not appear in a LINK clause", n->sym->name,
    6327              :                            &n->where);
    6328          499 :           n->sym->mark = 1;
    6329              :         }
    6330              :       else  /* common block  */
    6331              :         {
    6332           41 :           if (n->u.common->omp_groupprivate && list != OMP_LIST_LOCAL)
    6333            7 :             gfc_error_now ("Common block %</%s/%> at %L not appear in the %qs "
    6334              :                            "clause as it was previously specified in a "
    6335              :                            "GROUPPRIVATE directive",
    6336            7 :                            n->u.common->name, &n->where,
    6337              :                            list == OMP_LIST_LINK
    6338            5 :                            ? "link" : list == OMP_LIST_TO ? "to" : "enter");
    6339           34 :           else if (n->u.common->head && n->u.common->head->mark)
    6340            4 :             gfc_error_now ("Common block %</%s/%> at %L mentioned multiple "
    6341              :                            "times in clauses of the same OMP DECLARE TARGET "
    6342            4 :                            "directive", n->u.common->name, &n->where);
    6343           30 :           else if ((n->u.common->omp_declare_target_link
    6344           26 :                     || n->u.common->omp_declare_target_local)
    6345              :                    && list != OMP_LIST_LINK
    6346            6 :                    && list != OMP_LIST_LOCAL)
    6347            2 :             gfc_error_now ("Common block %</%s/%> at %L previously mentioned "
    6348              :                            "in %s clause and later in %s clause",
    6349            1 :                            n->u.common->name, &n->where,
    6350              :                            n->u.common->omp_declare_target_link ? "LINK"
    6351              :                                                                 : "LOCAL",
    6352              :                            list == OMP_LIST_TO ? "TO" : "ENTER");
    6353           29 :           else if (n->u.common->omp_declare_target
    6354            4 :                    && (list == OMP_LIST_LINK || list == OMP_LIST_LOCAL))
    6355            1 :             gfc_error_now ("Common block %</%s/%> at %L previously mentioned "
    6356              :                            "in TO or ENTER clause and later in %s clause",
    6357            1 :                            n->u.common->name, &n->where,
    6358              :                            list == OMP_LIST_LINK ? "LINK" : "LOCAL");
    6359           41 :           if (n->u.common->omp_device_type != OMP_DEVICE_TYPE_UNSET
    6360           21 :               && n->u.common->omp_device_type != c->device_type)
    6361              :             {
    6362            1 :               const char *dt = "any";
    6363            1 :               if (n->u.common->omp_device_type == OMP_DEVICE_TYPE_NOHOST)
    6364              :                 dt = "nohost";
    6365            0 :               else if (n->u.common->omp_device_type == OMP_DEVICE_TYPE_HOST)
    6366            0 :                 dt = "host";
    6367            1 :               if (n->u.common->omp_groupprivate)
    6368            1 :                 gfc_error_now ("Common block %</%s/%> at %L set in previous OMP "
    6369              :                                "GROUPPRIVATE directive to the different "
    6370            1 :                                "DEVICE_TYPE %qs", n->u.common->name, &n->where,
    6371              :                                 dt);
    6372              :               else
    6373            0 :                 gfc_error_now ("Common block %</%s/%> at %L set in previous OMP "
    6374              :                                "DECLARE TARGET directive to the different "
    6375            0 :                                "DEVICE_TYPE %qs", n->u.common->name, &n->where,
    6376              :                                 dt);
    6377              :             }
    6378           41 :           n->u.common->omp_device_type = c->device_type;
    6379              : 
    6380           41 :           if (c->indirect && c->device_type != OMP_DEVICE_TYPE_ANY)
    6381              :             {
    6382            0 :               gfc_error_now ("DEVICE_TYPE must be ANY when used with INDIRECT "
    6383              :                              "at %L", &n->where);
    6384            0 :               c->indirect = 0;
    6385              :             }
    6386           41 :           if (list == OMP_LIST_LINK && c->device_type == OMP_DEVICE_TYPE_NOHOST)
    6387            1 :             gfc_error_now ("Common block %</%s/%> at %L set with NOHOST "
    6388              :                            "specified may not appear in a LINK clause",
    6389            1 :                            n->u.common->name, &n->where);
    6390              : 
    6391           41 :           if (list == OMP_LIST_TO || list == OMP_LIST_ENTER)
    6392           21 :             n->u.common->omp_declare_target = 1;
    6393           41 :           if (list == OMP_LIST_LINK)
    6394           15 :             n->u.common->omp_declare_target_link = 1;
    6395           41 :           if (list == OMP_LIST_LOCAL)
    6396            5 :             n->u.common->omp_declare_target_local = 1;
    6397              : 
    6398          110 :           for (s = n->u.common->head; s; s = s->common_next)
    6399              :             {
    6400           69 :               s->mark = 1;
    6401           69 :               if (list == OMP_LIST_TO || list == OMP_LIST_ENTER)
    6402           33 :                 gfc_add_omp_declare_target (&s->attr, s->name, &n->where);
    6403           69 :               if (list == OMP_LIST_LINK)
    6404           31 :                 gfc_add_omp_declare_target_link (&s->attr, s->name, &n->where);
    6405           69 :               if (list == OMP_LIST_LOCAL)
    6406            5 :                 gfc_add_omp_declare_target_local (&s->attr, s->name, &n->where);
    6407           69 :               s->attr.omp_device_type = c->device_type;
    6408           69 :               s->attr.omp_declare_target_indirect = c->indirect;
    6409              :             }
    6410              :         }
    6411          323 :   if ((c->device_type || c->indirect)
    6412          323 :       && !c->lists[OMP_LIST_ENTER]
    6413          151 :       && !c->lists[OMP_LIST_TO]
    6414           47 :       && !c->lists[OMP_LIST_LINK]
    6415           10 :       && !c->lists[OMP_LIST_LOCAL])
    6416            2 :     gfc_warning_now (OPT_Wopenmp,
    6417              :                      "OMP DECLARE TARGET directive at %L with only "
    6418              :                      "DEVICE_TYPE or INDIRECT clauses is ignored",
    6419              :                      &old_loc);
    6420              : 
    6421          323 :   gfc_buffer_error (true);
    6422              : 
    6423          323 :   if (c)
    6424          323 :     gfc_free_omp_clauses (c);
    6425          323 :   return MATCH_YES;
    6426              : 
    6427            0 : syntax:
    6428            0 :   gfc_error ("Syntax error in !$OMP DECLARE TARGET list at %C");
    6429              : 
    6430            2 : cleanup:
    6431            2 :   gfc_current_locus = old_loc;
    6432            2 :   if (c)
    6433            0 :     gfc_free_omp_clauses (c);
    6434              :   return MATCH_ERROR;
    6435              : }
    6436              : 
    6437              : /* Skip over and ignore trait-property-extensions.
    6438              : 
    6439              :    trait-property-extension :
    6440              :      trait-property-name
    6441              :      identifier (trait-property-extension[, trait-property-extension[, ...]])
    6442              :      constant integer expression
    6443              :  */
    6444              : 
    6445              : static match gfc_ignore_trait_property_extension_list (void);
    6446              : 
    6447              : static match
    6448            7 : gfc_ignore_trait_property_extension (void)
    6449              : {
    6450            7 :   char buf[GFC_MAX_SYMBOL_LEN + 1];
    6451            7 :   gfc_expr *expr;
    6452              : 
    6453              :   /* Identifier form of trait-property name, possibly followed by
    6454              :      a list of (recursive) trait-property-extensions.  */
    6455            7 :   if (gfc_match_name (buf) == MATCH_YES)
    6456              :     {
    6457            0 :       if (gfc_match (" (") == MATCH_YES)
    6458            0 :         return gfc_ignore_trait_property_extension_list ();
    6459              :       return MATCH_YES;
    6460              :     }
    6461              : 
    6462              :   /* Literal constant.  */
    6463            7 :   if (gfc_match_literal_constant (&expr, 0) == MATCH_YES)
    6464              :     return MATCH_YES;
    6465              : 
    6466              :   /* FIXME: constant integer expressions.  */
    6467            0 :   gfc_error ("Expected trait-property-extension at %C");
    6468            0 :   return MATCH_ERROR;
    6469              : }
    6470              : 
    6471              : static match
    6472            5 : gfc_ignore_trait_property_extension_list (void)
    6473              : {
    6474            9 :   while (1)
    6475              :     {
    6476            7 :       if (gfc_ignore_trait_property_extension () != MATCH_YES)
    6477              :         return MATCH_ERROR;
    6478            7 :       if (gfc_match (" ,") == MATCH_YES)
    6479            2 :         continue;
    6480            5 :       if (gfc_match (" )") == MATCH_YES)
    6481              :         return MATCH_YES;
    6482            0 :       gfc_error ("expected %<)%> at %C");
    6483            0 :       return MATCH_ERROR;
    6484              :     }
    6485              : }
    6486              : 
    6487              : 
    6488              : match
    6489          110 : gfc_match_omp_interop (void)
    6490              : {
    6491          110 :   return match_omp (EXEC_OMP_INTEROP, OMP_INTEROP_CLAUSES);
    6492              : }
    6493              : 
    6494              : 
    6495              : /* OpenMP 5.0:
    6496              : 
    6497              :    trait-selector:
    6498              :      trait-selector-name[([trait-score:]trait-property[,trait-property[,...]])]
    6499              : 
    6500              :    trait-score:
    6501              :      score(score-expression)  */
    6502              : 
    6503              : static match
    6504          637 : gfc_match_omp_context_selector (gfc_omp_set_selector *oss)
    6505              : {
    6506          775 :   do
    6507              :     {
    6508          775 :       char selector[GFC_MAX_SYMBOL_LEN + 1];
    6509              : 
    6510          775 :       if (gfc_match_name (selector) != MATCH_YES)
    6511              :         {
    6512            2 :           gfc_error ("expected trait selector name at %C");
    6513           39 :           return MATCH_ERROR;
    6514              :         }
    6515              : 
    6516          773 :       gfc_omp_selector *os = gfc_get_omp_selector ();
    6517          773 :       if (oss->code == OMP_TRAIT_SET_CONSTRUCT
    6518          335 :           && !strcmp (selector, "do"))
    6519           48 :         os->code = OMP_TRAIT_CONSTRUCT_FOR;
    6520          725 :       else if (oss->code == OMP_TRAIT_SET_CONSTRUCT
    6521          287 :                && !strcmp (selector, "for"))
    6522            1 :         os->code = OMP_TRAIT_INVALID;
    6523              :       else
    6524          724 :         os->code = omp_lookup_ts_code (oss->code, selector);
    6525          773 :       os->next = oss->trait_selectors;
    6526          773 :       oss->trait_selectors = os;
    6527              : 
    6528          773 :       if (os->code == OMP_TRAIT_INVALID)
    6529              :         {
    6530           18 :           gfc_warning (OPT_Wopenmp,
    6531              :                        "unknown selector %qs for context selector set %qs "
    6532              :                        "at %C",
    6533           18 :                        selector, omp_tss_map[oss->code]);
    6534           18 :           if (gfc_match (" (") == MATCH_YES
    6535           18 :               && gfc_ignore_trait_property_extension_list () != MATCH_YES)
    6536              :             return MATCH_ERROR;
    6537           18 :           if (gfc_match (" ,") == MATCH_YES)
    6538            1 :             continue;
    6539          598 :           break;
    6540              :         }
    6541              : 
    6542          755 :       enum omp_tp_type property_kind = omp_ts_map[os->code].tp_type;
    6543          755 :       bool allow_score = omp_ts_map[os->code].allow_score;
    6544              : 
    6545          755 :       if (gfc_match (" (") == MATCH_YES)
    6546              :         {
    6547          431 :           if (property_kind == OMP_TRAIT_PROPERTY_NONE)
    6548              :             {
    6549            6 :               gfc_error ("selector %qs does not accept any properties at %C",
    6550              :                          selector);
    6551            6 :               return MATCH_ERROR;
    6552              :             }
    6553              : 
    6554          425 :           if (gfc_match (" score") == MATCH_YES)
    6555              :             {
    6556           63 :               if (!allow_score)
    6557              :                 {
    6558           10 :                   gfc_error ("%<score%> cannot be specified in traits "
    6559              :                              "in the %qs trait-selector-set at %C",
    6560           10 :                              omp_tss_map[oss->code]);
    6561           10 :                   return MATCH_ERROR;
    6562              :                 }
    6563           53 :               if (gfc_match (" (") != MATCH_YES)
    6564              :                 {
    6565            0 :                   gfc_error ("expected %<(%> at %C");
    6566            0 :                   return MATCH_ERROR;
    6567              :                 }
    6568           53 :               if (gfc_match_expr (&os->score) != MATCH_YES)
    6569              :                 return MATCH_ERROR;
    6570              : 
    6571           52 :               if (gfc_match (" )") != MATCH_YES)
    6572              :                 {
    6573            0 :                   gfc_error ("expected %<)%> at %C");
    6574            0 :                   return MATCH_ERROR;
    6575              :                 }
    6576              : 
    6577           52 :               if (gfc_match (" :") != MATCH_YES)
    6578              :                 {
    6579            0 :                   gfc_error ("expected : at %C");
    6580            0 :                   return MATCH_ERROR;
    6581              :                 }
    6582              :             }
    6583              : 
    6584          414 :           gfc_omp_trait_property *otp = gfc_get_omp_trait_property ();
    6585          414 :           otp->property_kind = property_kind;
    6586          414 :           otp->next = os->properties;
    6587          414 :           os->properties = otp;
    6588              : 
    6589          414 :           switch (property_kind)
    6590              :             {
    6591           25 :             case OMP_TRAIT_PROPERTY_ID:
    6592           25 :               {
    6593           25 :                 char buf[GFC_MAX_SYMBOL_LEN + 1];
    6594           25 :                 if (gfc_match_name (buf) == MATCH_YES)
    6595              :                   {
    6596           24 :                     otp->name = XNEWVEC (char, strlen (buf) + 1);
    6597           24 :                     strcpy (otp->name, buf);
    6598              :                   }
    6599              :                 else
    6600              :                   {
    6601            1 :                     gfc_error ("expected identifier at %C");
    6602            1 :                     free (otp);
    6603            1 :                     os->properties = nullptr;
    6604            1 :                     return MATCH_ERROR;
    6605              :                   }
    6606              :               }
    6607           24 :               break;
    6608          290 :             case OMP_TRAIT_PROPERTY_NAME_LIST:
    6609          343 :               do
    6610              :                 {
    6611          290 :                   char buf[GFC_MAX_SYMBOL_LEN + 1];
    6612          290 :                   if (gfc_match_name (buf) == MATCH_YES)
    6613              :                     {
    6614          170 :                       otp->name = XNEWVEC (char, strlen (buf) + 1);
    6615          170 :                       strcpy (otp->name, buf);
    6616          170 :                       otp->is_name = true;
    6617              :                     }
    6618          120 :                   else if (gfc_match_literal_constant (&otp->expr, 0)
    6619              :                            != MATCH_YES
    6620          120 :                            || otp->expr->ts.type != BT_CHARACTER)
    6621              :                     {
    6622            5 :                       gfc_error ("expected identifier or string literal "
    6623              :                                  "at %C");
    6624            5 :                       free (otp);
    6625            5 :                       os->properties = nullptr;
    6626            5 :                       return MATCH_ERROR;
    6627              :                     }
    6628              : 
    6629          285 :                   if (gfc_match (" ,") == MATCH_YES)
    6630              :                     {
    6631           53 :                       otp = gfc_get_omp_trait_property ();
    6632           53 :                       otp->property_kind = property_kind;
    6633           53 :                       otp->next = os->properties;
    6634           53 :                       os->properties = otp;
    6635              :                     }
    6636              :                   else
    6637              :                     break;
    6638           53 :                 }
    6639              :               while (1);
    6640          232 :               break;
    6641          137 :             case OMP_TRAIT_PROPERTY_DEV_NUM_EXPR:
    6642          137 :             case OMP_TRAIT_PROPERTY_BOOL_EXPR:
    6643          137 :               if (gfc_match_expr (&otp->expr) != MATCH_YES)
    6644              :                 {
    6645            3 :                   gfc_error ("expected expression at %C");
    6646            3 :                   free (otp);
    6647            3 :                   os->properties = nullptr;
    6648            3 :                   return MATCH_ERROR;
    6649              :                 }
    6650              :               break;
    6651           15 :             case OMP_TRAIT_PROPERTY_CLAUSE_LIST:
    6652           15 :               {
    6653           15 :                 if (os->code == OMP_TRAIT_CONSTRUCT_SIMD)
    6654              :                   {
    6655           15 :                     gfc_matching_omp_context_selector = true;
    6656           15 :                     if (gfc_match_omp_clauses (&otp->clauses,
    6657           15 :                                                OMP_DECLARE_SIMD_CLAUSES,
    6658              :                                                true, false, false)
    6659              :                         != MATCH_YES)
    6660              :                       {
    6661            1 :                         gfc_matching_omp_context_selector = false;
    6662            1 :                         gfc_error ("expected simd clause at %C");
    6663            1 :                         return MATCH_ERROR;
    6664              :                       }
    6665           14 :                     gfc_matching_omp_context_selector = false;
    6666              :                   }
    6667            0 :                 else if (os->code == OMP_TRAIT_IMPLEMENTATION_REQUIRES)
    6668              :                   {
    6669              :                     /* FIXME: The "requires" selector was added in OpenMP 5.1.
    6670              :                        Currently only the now-deprecated syntax
    6671              :                        from OpenMP 5.0 is supported.
    6672              :                        TODO: When implementing, update modules.cc as well.  */
    6673            0 :                     sorry_at (gfc_get_location (&gfc_current_locus),
    6674              :                               "%<requires%> selector is not supported yet");
    6675            0 :                     return MATCH_ERROR;
    6676              :                   }
    6677              :                 else
    6678            0 :                   gcc_unreachable ();
    6679           14 :                 break;
    6680              :               }
    6681            0 :             default:
    6682            0 :               gcc_unreachable ();
    6683              :             }
    6684              : 
    6685          404 :           if (gfc_match (" )") != MATCH_YES)
    6686              :             {
    6687            2 :               gfc_error ("expected %<)%> at %C");
    6688            2 :               return MATCH_ERROR;
    6689              :             }
    6690              :         }
    6691          324 :       else if (property_kind != OMP_TRAIT_PROPERTY_NONE
    6692          324 :                && property_kind != OMP_TRAIT_PROPERTY_CLAUSE_LIST
    6693            8 :                && property_kind != OMP_TRAIT_PROPERTY_EXTENSION)
    6694              :         {
    6695            8 :           if (gfc_match (" (") != MATCH_YES)
    6696              :             {
    6697            8 :               gfc_error ("expected %<(%> at %C");
    6698            8 :               return MATCH_ERROR;
    6699              :             }
    6700              :         }
    6701              : 
    6702          718 :       if (gfc_match (" ,") != MATCH_YES)
    6703              :         break;
    6704              :     }
    6705              :   while (1);
    6706              : 
    6707          598 :   return MATCH_YES;
    6708              : }
    6709              : 
    6710              : /* OpenMP 5.0:
    6711              : 
    6712              :    trait-set-selector[,trait-set-selector[,...]]
    6713              : 
    6714              :    trait-set-selector:
    6715              :      trait-set-selector-name = { trait-selector[, trait-selector[, ...]] }
    6716              : 
    6717              :    trait-set-selector-name:
    6718              :      constructor
    6719              :      device
    6720              :      implementation
    6721              :      user  */
    6722              : 
    6723              : static match
    6724          577 : gfc_match_omp_context_selector_specification (gfc_omp_set_selector **oss_head)
    6725              : {
    6726          713 :   do
    6727              :     {
    6728          645 :       match m;
    6729          645 :       char buf[GFC_MAX_SYMBOL_LEN + 1];
    6730          645 :       enum omp_tss_code set = OMP_TRAIT_SET_INVALID;
    6731              : 
    6732          645 :       m = gfc_match_name (buf);
    6733          645 :       if (m == MATCH_YES)
    6734          643 :         set = omp_lookup_tss_code (buf);
    6735              : 
    6736          643 :       if (set == OMP_TRAIT_SET_INVALID)
    6737              :         {
    6738            5 :           gfc_error ("expected context selector set name at %C");
    6739           47 :           return MATCH_ERROR;
    6740              :         }
    6741              : 
    6742          640 :       m = gfc_match (" =");
    6743          640 :       if (m != MATCH_YES)
    6744              :         {
    6745            1 :           gfc_error ("expected %<=%> at %C");
    6746            1 :           return MATCH_ERROR;
    6747              :         }
    6748              : 
    6749          639 :       m = gfc_match (" {");
    6750          639 :       if (m != MATCH_YES)
    6751              :         {
    6752            2 :           gfc_error ("expected %<{%> at %C");
    6753            2 :           return MATCH_ERROR;
    6754              :         }
    6755              : 
    6756          637 :       gfc_omp_set_selector *oss = gfc_get_omp_set_selector ();
    6757          637 :       oss->next = *oss_head;
    6758          637 :       oss->code = set;
    6759          637 :       *oss_head = oss;
    6760              : 
    6761          637 :       if (gfc_match_omp_context_selector (oss) != MATCH_YES)
    6762              :         return MATCH_ERROR;
    6763              : 
    6764          598 :       m = gfc_match (" }");
    6765          598 :       if (m != MATCH_YES)
    6766              :         {
    6767            0 :           gfc_error ("expected %<}%> at %C");
    6768            0 :           return MATCH_ERROR;
    6769              :         }
    6770              : 
    6771          598 :       m = gfc_match (" ,");
    6772          598 :       if (m != MATCH_YES)
    6773              :         break;
    6774           68 :     }
    6775              :   while (1);
    6776              : 
    6777          530 :   return MATCH_YES;
    6778              : }
    6779              : 
    6780              : 
    6781              : match
    6782          418 : gfc_match_omp_declare_variant (void)
    6783              : {
    6784          418 :   char buf[GFC_MAX_SYMBOL_LEN + 1];
    6785              : 
    6786          418 :   if (gfc_match (" (") != MATCH_YES)
    6787              :     {
    6788            2 :       gfc_error ("expected %<(%> at %C");
    6789            2 :       return MATCH_ERROR;
    6790              :     }
    6791              : 
    6792          416 :   gfc_symtree *base_proc_st, *variant_proc_st;
    6793          416 :   if (gfc_match_name (buf) != MATCH_YES)
    6794              :     {
    6795            2 :       gfc_error ("expected name at %C");
    6796            2 :       return MATCH_ERROR;
    6797              :     }
    6798              : 
    6799          414 :   if (gfc_get_ha_sym_tree (buf, &base_proc_st))
    6800              :     return MATCH_ERROR;
    6801              : 
    6802          414 :   if (gfc_match (" :") == MATCH_YES)
    6803              :     {
    6804           15 :       if (gfc_match_name (buf) != MATCH_YES)
    6805              :         {
    6806            0 :           gfc_error ("expected variant name at %C");
    6807            0 :           return MATCH_ERROR;
    6808              :         }
    6809              : 
    6810           15 :       if (gfc_get_ha_sym_tree (buf, &variant_proc_st))
    6811              :         return MATCH_ERROR;
    6812              :     }
    6813              :   else
    6814              :     {
    6815              :       /* Base procedure not specified.  */
    6816          399 :       variant_proc_st = base_proc_st;
    6817          399 :       base_proc_st = NULL;
    6818              :     }
    6819              : 
    6820          414 :   gfc_omp_declare_variant *odv;
    6821          414 :   odv = gfc_get_omp_declare_variant ();
    6822          414 :   odv->where = gfc_current_locus;
    6823          414 :   odv->variant_proc_symtree = variant_proc_st;
    6824          414 :   odv->adjust_args_list = NULL;
    6825          414 :   odv->base_proc_symtree = base_proc_st;
    6826          414 :   odv->next = NULL;
    6827          414 :   odv->error_p = false;
    6828              : 
    6829              :   /* Add the new declare variant to the end of the list.  */
    6830          414 :   gfc_omp_declare_variant **prev_next = &gfc_current_ns->omp_declare_variant;
    6831          554 :   while (*prev_next)
    6832          140 :     prev_next = &((*prev_next)->next);
    6833          414 :   *prev_next = odv;
    6834              : 
    6835          414 :   if (gfc_match (" )") != MATCH_YES)
    6836              :     {
    6837            0 :       gfc_error ("expected %<)%> at %C");
    6838            0 :       return MATCH_ERROR;
    6839              :     }
    6840              : 
    6841          414 :   bool has_match = false, has_adjust_args = false, has_append_args = false;
    6842          414 :   bool error_p = false;
    6843          414 :   locus adjust_args_loc;
    6844          414 :   locus append_args_loc;
    6845              : 
    6846          414 :   gfc_gobble_whitespace ();
    6847          414 :   gfc_match_char (',');
    6848          632 :   for (;;)
    6849              :     {
    6850          523 :       gfc_gobble_whitespace ();
    6851              : 
    6852          523 :       enum clause
    6853              :       {
    6854              :         clause_match,
    6855              :         clause_adjust_args,
    6856              :         clause_append_args
    6857              :       } ccode;
    6858              : 
    6859          523 :       if (gfc_match ("match") == MATCH_YES)
    6860              :         ccode = clause_match;
    6861          119 :       else if (gfc_match ("adjust_args") == MATCH_YES)
    6862              :         {
    6863          517 :           ccode = clause_adjust_args;
    6864              :           adjust_args_loc = gfc_current_locus;
    6865              :         }
    6866           38 :       else if (gfc_match ("append_args") == MATCH_YES)
    6867              :         {
    6868          517 :           ccode = clause_append_args;
    6869              :           append_args_loc = gfc_current_locus;
    6870              :         }
    6871              :       else
    6872              :         {
    6873              :           error_p = true;
    6874              :           break;
    6875              :         }
    6876              : 
    6877          517 :       if (gfc_match (" ( ") != MATCH_YES)
    6878              :         {
    6879            1 :           gfc_error ("expected %<(%> at %C");
    6880            1 :           return MATCH_ERROR;
    6881              :         }
    6882              : 
    6883          516 :       if (ccode == clause_match)
    6884              :         {
    6885          403 :           if (has_match)
    6886              :             {
    6887            1 :               gfc_error ("%qs clause at %L specified more than once",
    6888              :                          "match", &gfc_current_locus);
    6889            1 :               return MATCH_ERROR;
    6890              :             }
    6891          402 :           has_match = true;
    6892          402 :           if (gfc_match_omp_context_selector_specification (&odv->set_selectors)
    6893              :               != MATCH_YES)
    6894              :             return MATCH_ERROR;
    6895          362 :           if (gfc_match (" )") != MATCH_YES)
    6896              :             {
    6897            0 :               gfc_error ("expected %<)%> at %C");
    6898            0 :               return MATCH_ERROR;
    6899              :             }
    6900              :         }
    6901          113 :       else if (ccode == clause_adjust_args)
    6902              :         {
    6903           81 :           has_adjust_args = true;
    6904           81 :           bool need_device_ptr_p = false;
    6905           81 :           bool need_device_addr_p = false;
    6906           81 :           if (gfc_match ("nothing ") == MATCH_YES)
    6907              :             ;
    6908           58 :           else if (gfc_match ("need_device_ptr ") == MATCH_YES)
    6909              :             need_device_ptr_p = true;
    6910            9 :           else if (gfc_match ("need_device_addr ") == MATCH_YES)
    6911              :             need_device_addr_p = true;
    6912              :           else
    6913              :             {
    6914            2 :               gfc_error ("expected %<nothing%>, %<need_device_ptr%> or "
    6915              :                          "%<need_device_addr%> at %C");
    6916            2 :               return MATCH_ERROR;
    6917              :             }
    6918           79 :           if (gfc_match (": ") != MATCH_YES)
    6919              :             {
    6920            1 :               gfc_error ("expected %<:%> at %C");
    6921            1 :               return MATCH_ERROR;
    6922              :             }
    6923              :           gfc_omp_namelist *tail = NULL;
    6924              :           bool need_range = false, have_range = false;
    6925          125 :           while (true)
    6926              :             {
    6927          125 :               gfc_omp_namelist *p = gfc_get_omp_namelist ();
    6928          125 :               p->where = gfc_current_locus;
    6929          125 :               p->u.adj_args.need_ptr = need_device_ptr_p;
    6930          125 :               p->u.adj_args.need_addr = need_device_addr_p;
    6931          125 :               if (tail)
    6932              :                 {
    6933           47 :                   tail->next = p;
    6934           47 :                   tail = tail->next;
    6935              :                 }
    6936              :               else
    6937              :                 {
    6938           78 :                   gfc_omp_namelist **q = &odv->adjust_args_list;
    6939           78 :                   if (*q)
    6940              :                     {
    6941           50 :                       for (; (*q)->next; q = &(*q)->next)
    6942              :                         ;
    6943           28 :                       (*q)->next = p;
    6944              :                     }
    6945              :                   else
    6946           50 :                     *q = p;
    6947              :                   tail = p;
    6948              :                 }
    6949          125 :               if (gfc_match (": ") == MATCH_YES)
    6950              :                 {
    6951            2 :                   if (have_range)
    6952              :                     {
    6953            0 :                       gfc_error ("unexpected %<:%> at %C");
    6954            2 :                       return MATCH_ERROR;
    6955              :                     }
    6956            2 :                   p->u.adj_args.range_start = have_range = true;
    6957            2 :                   need_range = false;
    6958           49 :                   continue;
    6959              :                 }
    6960          123 :               if (have_range && gfc_match (", ") == MATCH_YES)
    6961              :                 {
    6962            1 :                  have_range = false;
    6963            1 :                  continue;
    6964              :                 }
    6965          122 :               if (have_range && gfc_match (") ") == MATCH_YES)
    6966              :                 break;
    6967          121 :               locus saved_loc = gfc_current_locus;
    6968              : 
    6969              :               /* Without ranges, only arg names or integer literals permitted;
    6970              :                  handle literals here as gfc_match_expr simplifies the expr.  */
    6971          121 :               if (gfc_match_literal_constant (&p->expr, true) == MATCH_YES)
    6972              :                 {
    6973           17 :                   gfc_gobble_whitespace ();
    6974           17 :                   char c = gfc_peek_ascii_char ();
    6975           17 :                   if (c != ')' && c != ',' && c != ':')
    6976              :                     {
    6977            1 :                       gfc_free_expr (p->expr);
    6978            1 :                       p->expr = NULL;
    6979            1 :                       gfc_current_locus = saved_loc;
    6980              :                     }
    6981              :                 }
    6982          121 :               if (!p->expr && gfc_match ("omp_num_args") == MATCH_YES)
    6983              :                 {
    6984            6 :                   if (!have_range)
    6985            3 :                     p->u.adj_args.range_start = need_range = true;
    6986              :                   else
    6987              :                     need_range = false;
    6988              : 
    6989            6 :                   locus saved_loc2 = gfc_current_locus;
    6990            6 :                   gfc_gobble_whitespace ();
    6991            6 :                   char c = gfc_peek_ascii_char ();
    6992            6 :                   if (c == '+' || c == '-')
    6993              :                     {
    6994            5 :                       if (gfc_match ("+ %e", &p->expr) == MATCH_YES)
    6995            1 :                         p->u.adj_args.omp_num_args_plus = true;
    6996            4 :                       else if (gfc_match ("- %e", &p->expr) == MATCH_YES)
    6997            4 :                         p->u.adj_args.omp_num_args_minus = true;
    6998            0 :                       else if (!gfc_error_check ())
    6999              :                         {
    7000            0 :                           gfc_error ("expected constant integer expression "
    7001              :                                      "at %C");
    7002            0 :                           p->u.adj_args.error_p = true;
    7003            0 :                           return MATCH_ERROR;
    7004              :                         }
    7005            5 :                       p->where = gfc_get_location_range (&saved_loc, 1,
    7006              :                                                          &saved_loc, 1,
    7007              :                                                          &gfc_current_locus);
    7008              :                     }
    7009              :                   else
    7010              :                     {
    7011            1 :                       p->where = gfc_get_location_range (&saved_loc, 1,
    7012              :                                                          &saved_loc, 1,
    7013              :                                                          &saved_loc2);
    7014            1 :                       p->u.adj_args.omp_num_args_plus = true;
    7015              :                     }
    7016              :                 }
    7017          115 :               else if (!p->expr)
    7018              :                 {
    7019           99 :                   match m = gfc_match_expr (&p->expr);
    7020           99 :                   if (m != MATCH_YES)
    7021              :                     {
    7022            1 :                       gfc_error ("expected dummy parameter name, "
    7023              :                                  "%<omp_num_args%> or constant positive integer"
    7024              :                                  " at %C");
    7025            1 :                       p->u.adj_args.error_p = true;
    7026            1 :                       return MATCH_ERROR;
    7027              :                     }
    7028           98 :                   if (p->expr->expr_type == EXPR_CONSTANT && !have_range)
    7029           98 :                     need_range = true;  /* Constant expr but not literal.  */
    7030           98 :                   p->where = p->expr->where;
    7031              :                 }
    7032              :               else
    7033           16 :                 p->where = p->expr->where;
    7034          120 :               gfc_gobble_whitespace ();
    7035          120 :               match m = gfc_match (": ");
    7036          120 :               if (need_range && m != MATCH_YES)
    7037              :                 {
    7038            1 :                   gfc_error ("expected %<:%> at %C");
    7039            1 :                   return MATCH_ERROR;
    7040              :                 }
    7041          119 :               if (m == MATCH_YES)
    7042              :                 {
    7043            6 :                   p->u.adj_args.range_start = have_range = true;
    7044            6 :                   need_range = false;
    7045            6 :                   continue;
    7046              :                 }
    7047          113 :               need_range = have_range = false;
    7048          113 :               if (gfc_match (", ") == MATCH_YES)
    7049           38 :                 continue;
    7050           75 :               if (gfc_match (") ") == MATCH_YES)
    7051              :                 break;
    7052              :             }
    7053              :         }
    7054           32 :       else if (ccode == clause_append_args)
    7055              :         {
    7056           32 :           if (has_append_args)
    7057              :             {
    7058            1 :               gfc_error ("%qs clause at %L specified more than once",
    7059              :                          "append_args", &gfc_current_locus);
    7060            1 :               return MATCH_ERROR;
    7061              :             }
    7062           56 :           has_append_args = true;
    7063              :           gfc_omp_namelist *append_args_last = NULL;
    7064           81 :           do
    7065              :             {
    7066           56 :               gfc_gobble_whitespace ();
    7067           56 :               if (gfc_match ("interop ") != MATCH_YES)
    7068              :                 {
    7069            0 :                   gfc_error ("expected %<interop%> at %C");
    7070            3 :                   return MATCH_ERROR;
    7071              :                 }
    7072           56 :               if (gfc_match ("( ") != MATCH_YES)
    7073              :                 {
    7074            0 :                   gfc_error ("expected %<(%> at %C");
    7075            0 :                   return MATCH_ERROR;
    7076              :                 }
    7077              : 
    7078           56 :               bool target, targetsync;
    7079           56 :               char *type_str = NULL;
    7080           56 :               int type_str_len;
    7081           56 :               locus loc = gfc_current_locus;
    7082           56 :               if (gfc_parser_omp_clause_init_modifiers (target, targetsync,
    7083              :                                                         &type_str, type_str_len,
    7084              :                                                         false) == MATCH_ERROR)
    7085              :                 return MATCH_ERROR;
    7086              : 
    7087           54 :               gfc_omp_namelist *n = gfc_get_omp_namelist();
    7088           54 :               n->where = loc;
    7089           54 :               n->u.init.target = target;
    7090           54 :               n->u.init.targetsync = targetsync;
    7091           54 :               n->u.init.len = type_str_len;
    7092           54 :               n->u2.init_interop = type_str;
    7093           54 :               if (odv->append_args_list)
    7094              :                 {
    7095           25 :                   append_args_last->next = n;
    7096           25 :                   append_args_last = n;
    7097              :                 }
    7098              :               else
    7099           29 :                 append_args_last = odv->append_args_list = n;
    7100              : 
    7101           54 :               gfc_gobble_whitespace ();
    7102           54 :               if (gfc_match_char (',') == MATCH_YES)
    7103           25 :                 continue;
    7104           29 :               if (gfc_match_char (')') == MATCH_YES)
    7105              :                 break;
    7106            1 :               gfc_error ("Expected %<,%> or %<)%> at %C");
    7107            1 :               return MATCH_ERROR;
    7108              :             }
    7109              :           while (true);
    7110              :         }
    7111          466 :       gfc_gobble_whitespace ();
    7112          466 :       if (gfc_match_omp_eos () == MATCH_YES)
    7113              :         break;
    7114          109 :       gfc_match_char (',');
    7115          109 :     }
    7116              : 
    7117          363 :   if (error_p || (!has_match && !has_adjust_args && !has_append_args))
    7118              :     {
    7119            6 :       gfc_error ("expected %<match%>, %<adjust_args%> or %<append_args%> at %C");
    7120            6 :       return MATCH_ERROR;
    7121              :     }
    7122              : 
    7123          357 :   if (!has_match)
    7124              :     {
    7125            3 :       gfc_error ("expected %<match%> clause at %C");
    7126            3 :       return MATCH_ERROR;
    7127              :     }
    7128              : 
    7129              :   return MATCH_YES;
    7130              : }
    7131              : 
    7132              : 
    7133              : static match
    7134          160 : match_omp_metadirective (bool begin_p)
    7135              : {
    7136          160 :   locus old_loc = gfc_current_locus;
    7137          160 :   gfc_omp_variant *variants_head;
    7138          160 :   gfc_omp_variant **next_variant = &variants_head;
    7139          160 :   bool default_seen = false;
    7140              : 
    7141              :   /* Parse the context selectors.  */
    7142          656 :   for (;;)
    7143              :     {
    7144          408 :       bool default_p = false;
    7145          408 :       gfc_omp_set_selector *selectors = NULL;
    7146              : 
    7147          408 :       gfc_gobble_whitespace ();
    7148          408 :       if (gfc_match_eos () == MATCH_YES)
    7149              :         break;
    7150          266 :       gfc_match_char (',');
    7151          266 :       gfc_gobble_whitespace ();
    7152              : 
    7153          266 :       locus variant_locus = gfc_current_locus;
    7154              : 
    7155          266 :       if (gfc_match ("default ( ") == MATCH_YES)
    7156              :         {
    7157           82 :           default_p = true;
    7158           82 :           gfc_warning (OPT_Wdeprecated_openmp,
    7159              :                        "%<default%> clause with metadirective at %L "
    7160              :                        "deprecated since OpenMP 5.2", &variant_locus);
    7161              :         }
    7162          184 :       else if (gfc_match ("otherwise ( ") == MATCH_YES)
    7163              :         default_p = true;
    7164          177 :       else if (gfc_match ("when ( ") != MATCH_YES)
    7165              :         {
    7166            1 :           gfc_error ("expected %<when%>, %<otherwise%>, or %<default%> at %C");
    7167            1 :           gfc_current_locus = old_loc;
    7168           18 :           return MATCH_ERROR;
    7169              :         }
    7170           89 :       if (default_p && default_seen)
    7171              :         {
    7172            3 :           gfc_error ("too many %<otherwise%> or %<default%> clauses "
    7173              :                      "in %<metadirective%> at %C");
    7174            3 :           gfc_current_locus = old_loc;
    7175            3 :           return MATCH_ERROR;
    7176              :         }
    7177          262 :       else if (default_seen)
    7178              :         {
    7179            1 :           gfc_error ("%<otherwise%> or %<default%> clause "
    7180              :                      "must appear last in %<metadirective%> at %C");
    7181            1 :           gfc_current_locus = old_loc;
    7182            1 :           return MATCH_ERROR;
    7183              :         }
    7184              : 
    7185          261 :       if (!default_p)
    7186              :         {
    7187          175 :           if (gfc_match_omp_context_selector_specification (&selectors)
    7188              :               != MATCH_YES)
    7189              :             return MATCH_ERROR;
    7190              : 
    7191          168 :           if (gfc_match (" : ") != MATCH_YES)
    7192              :             {
    7193            1 :               gfc_error ("expected %<:%> at %C");
    7194            1 :               gfc_current_locus = old_loc;
    7195            1 :               return MATCH_ERROR;
    7196              :             }
    7197              : 
    7198          167 :           gfc_commit_symbols ();
    7199              :         }
    7200              : 
    7201          253 :       gfc_matching_omp_context_selector = true;
    7202          253 :       gfc_statement directive = match_omp_directive ();
    7203          253 :       gfc_matching_omp_context_selector = false;
    7204              : 
    7205          253 :       if (is_omp_declarative_stmt (directive))
    7206            0 :         sorry_at (gfc_get_location (&gfc_current_locus),
    7207              :                   "declarative directive variants are not supported");
    7208              : 
    7209          253 :       if (gfc_error_flag_test ())
    7210              :         {
    7211            2 :           gfc_current_locus = old_loc;
    7212            2 :           return MATCH_ERROR;
    7213              :         }
    7214              : 
    7215          251 :       if (gfc_match (" )") != MATCH_YES)
    7216              :         {
    7217            0 :           gfc_error ("Expected %<)%> at %C");
    7218            0 :           gfc_current_locus = old_loc;
    7219            0 :           return MATCH_ERROR;
    7220              :         }
    7221              : 
    7222          251 :       gfc_commit_symbols ();
    7223              : 
    7224          251 :       if (begin_p
    7225          251 :           && directive != ST_NONE
    7226          251 :           && gfc_omp_end_stmt (directive) == ST_NONE)
    7227              :         {
    7228            3 :           gfc_error ("variant directive used in OMP BEGIN METADIRECTIVE "
    7229              :                      "at %C must have a corresponding end directive");
    7230            3 :           gfc_current_locus = old_loc;
    7231            3 :           return MATCH_ERROR;
    7232              :         }
    7233              : 
    7234          248 :       if (default_p)
    7235              :         default_seen = true;
    7236              : 
    7237          248 :       gfc_omp_variant *omv = gfc_get_omp_variant ();
    7238          248 :       omv->selectors = selectors;
    7239          248 :       omv->stmt = directive;
    7240          248 :       omv->where = variant_locus;
    7241              : 
    7242          248 :       if (directive == ST_NONE)
    7243              :         {
    7244              :           /* The directive was a 'nothing' directive.  */
    7245           15 :           omv->code = gfc_get_code (EXEC_CONTINUE);
    7246           15 :           omv->code->ext.omp_clauses = NULL;
    7247              :         }
    7248              :       else
    7249              :         {
    7250          233 :           omv->code = gfc_get_code (new_st.op);
    7251          233 :           omv->code->ext.omp_clauses = new_st.ext.omp_clauses;
    7252              :           /* Prevent the OpenMP clauses from being freed via NEW_ST.  */
    7253          233 :           new_st.ext.omp_clauses = NULL;
    7254              :         }
    7255              : 
    7256          248 :       *next_variant = omv;
    7257          248 :       next_variant = &omv->next;
    7258          248 :     }
    7259              : 
    7260          142 :   if (gfc_match_omp_eos () != MATCH_YES)
    7261              :     {
    7262            0 :       gfc_error ("Unexpected junk after OMP METADIRECTIVE at %C");
    7263            0 :       gfc_current_locus = old_loc;
    7264            0 :       return MATCH_ERROR;
    7265              :     }
    7266              : 
    7267              :   /* Add a 'default (nothing)' clause if no default is explicitly given.  */
    7268          142 :   if (!default_seen)
    7269              :     {
    7270           65 :       gfc_omp_variant *omv = gfc_get_omp_variant ();
    7271           65 :       omv->stmt = ST_NONE;
    7272           65 :       omv->code = gfc_get_code (EXEC_CONTINUE);
    7273           65 :       omv->code->ext.omp_clauses = NULL;
    7274           65 :       omv->where = old_loc;
    7275           65 :       omv->selectors = NULL;
    7276              : 
    7277           65 :       *next_variant = omv;
    7278           65 :       next_variant = &omv->next;
    7279              :     }
    7280              : 
    7281          142 :   new_st.op = EXEC_OMP_METADIRECTIVE;
    7282          142 :   new_st.ext.omp_variants = variants_head;
    7283              : 
    7284          142 :   return MATCH_YES;
    7285              : }
    7286              : 
    7287              : match
    7288           43 : gfc_match_omp_begin_metadirective (void)
    7289              : {
    7290           43 :   return match_omp_metadirective (true);
    7291              : }
    7292              : 
    7293              : match
    7294          117 : gfc_match_omp_metadirective (void)
    7295              : {
    7296          117 :   return match_omp_metadirective (false);
    7297              : }
    7298              : 
    7299              : /* Match 'omp threadprivate' or 'omp groupprivate'.  */
    7300              : static match
    7301          259 : gfc_match_omp_thread_group_private (bool is_groupprivate)
    7302              : {
    7303          259 :   locus old_loc;
    7304          259 :   char n[GFC_MAX_SYMBOL_LEN+1];
    7305          259 :   gfc_symbol *sym;
    7306          259 :   match m;
    7307          259 :   gfc_symtree *st;
    7308          259 :   struct sym_loc_t { gfc_symbol *sym; gfc_common_head *com; locus loc; };
    7309          259 :   auto_vec<sym_loc_t> syms;
    7310              : 
    7311          259 :   old_loc = gfc_current_locus;
    7312              : 
    7313          259 :   m = gfc_match (" ( ");
    7314          259 :   if (m != MATCH_YES)
    7315              :     return m;
    7316              : 
    7317          369 :   for (;;)
    7318              :     {
    7319          314 :       locus sym_loc = gfc_current_locus;
    7320          314 :       m = gfc_match_symbol (&sym, 0);
    7321          314 :       switch (m)
    7322              :         {
    7323          209 :         case MATCH_YES:
    7324          209 :           if (sym->attr.in_common)
    7325            0 :             gfc_error_now ("%qs variable at %L is an element of a COMMON block",
    7326              :                            is_groupprivate ? "groupprivate" : "threadprivate",
    7327              :                            &sym_loc);
    7328          209 :           else if (!is_groupprivate
    7329          209 :                    && !gfc_add_threadprivate (&sym->attr, sym->name, &sym_loc))
    7330           16 :             goto cleanup;
    7331          207 :           else if (is_groupprivate)
    7332              :             {
    7333           30 :               if (!gfc_add_omp_groupprivate (&sym->attr, sym->name, &sym_loc))
    7334            4 :                 goto cleanup;
    7335           26 :               syms.safe_push ({sym, nullptr, sym_loc});
    7336              :             }
    7337          203 :           goto next_item;
    7338              :         case MATCH_NO:
    7339              :           break;
    7340            0 :         case MATCH_ERROR:
    7341            0 :           goto cleanup;
    7342              :         }
    7343              : 
    7344          105 :       m = gfc_match (" / %n /", n);
    7345          105 :       if (m == MATCH_ERROR)
    7346            0 :         goto cleanup;
    7347          105 :       if (m == MATCH_NO || n[0] == '\0')
    7348            0 :         goto syntax;
    7349              : 
    7350          105 :       st = gfc_find_symtree (gfc_current_ns->common_root, n);
    7351          105 :       if (st == NULL)
    7352              :         {
    7353            2 :           gfc_error ("COMMON block /%s/ not found at %L", n, &sym_loc);
    7354            2 :           goto cleanup;
    7355              :         }
    7356          103 :       syms.safe_push ({nullptr, st->n.common, sym_loc});
    7357          103 :       if (is_groupprivate)
    7358           30 :         st->n.common->omp_groupprivate = 1;
    7359              :       else
    7360           73 :         st->n.common->threadprivate = 1;
    7361          236 :       for (sym = st->n.common->head; sym; sym = sym->common_next)
    7362          141 :         if (!is_groupprivate
    7363          141 :             && !gfc_add_threadprivate (&sym->attr, sym->name, &sym_loc))
    7364            3 :           goto cleanup;
    7365          138 :         else if (is_groupprivate
    7366          138 :                  && !gfc_add_omp_groupprivate (&sym->attr, sym->name, &sym_loc))
    7367            5 :           goto cleanup;
    7368              : 
    7369           95 :     next_item:
    7370          298 :       if (gfc_match_char (')') == MATCH_YES)
    7371              :         break;
    7372           55 :       if (gfc_match_char (',') != MATCH_YES)
    7373            0 :         goto syntax;
    7374           55 :     }
    7375              : 
    7376          243 :   if (is_groupprivate)
    7377              :     {
    7378           39 :       gfc_omp_clauses *c;
    7379           39 :       m = gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_DEVICE_TYPE));
    7380           39 :       if (m == MATCH_ERROR)
    7381            0 :         return MATCH_ERROR;
    7382              : 
    7383           39 :       if (c->device_type == OMP_DEVICE_TYPE_UNSET)
    7384           19 :         c->device_type = OMP_DEVICE_TYPE_ANY;
    7385              : 
    7386           86 :       for (size_t i = 0; i < syms.length (); i++)
    7387           47 :         if (syms[i].sym)
    7388              :           {
    7389           24 :             sym_loc_t &n = syms[i];
    7390           24 :             if (n.sym->attr.in_common)
    7391            0 :               gfc_error_now ("Variable %qs at %L is an element of a COMMON "
    7392              :                              "block", n.sym->name, &n.loc);
    7393           24 :             else if (n.sym->attr.omp_declare_target
    7394           23 :                      || n.sym->attr.omp_declare_target_link)
    7395            2 :               gfc_error_now ("List item %qs at %L implies OMP DECLARE TARGET "
    7396              :                              "with the LOCAL clause, but it has been specified"
    7397              :                              " with a different clause before",
    7398              :                              n.sym->name, &n.loc);
    7399           24 :             if (n.sym->attr.omp_device_type != OMP_DEVICE_TYPE_UNSET
    7400            5 :                 && n.sym->attr.omp_device_type != c->device_type)
    7401              :               {
    7402            2 :               const char *dt = "any";
    7403            2 :               if (n.sym->attr.omp_device_type == OMP_DEVICE_TYPE_HOST)
    7404              :                 dt = "host";
    7405            0 :               else if (n.sym->attr.omp_device_type == OMP_DEVICE_TYPE_NOHOST)
    7406            0 :                 dt = "nohost";
    7407            2 :               gfc_error_now ("List item %qs at %L set in previous OMP DECLARE "
    7408              :                              "TARGET directive to the different DEVICE_TYPE %qs",
    7409              :                              n.sym->name, &n.loc, dt);
    7410              :               }
    7411           24 :             gfc_add_omp_declare_target_local (&n.sym->attr, n.sym->name,
    7412              :                                               &n.loc);
    7413           24 :             n.sym->attr.omp_device_type = c->device_type;
    7414              :           }
    7415              :         else  /* Common block.  */
    7416              :           {
    7417           23 :             sym_loc_t &n = syms[i];
    7418           23 :             if (n.com->omp_declare_target
    7419           22 :                 || n.com->omp_declare_target_link)
    7420            2 :               gfc_error_now ("List item %</%s/%> at %L implies OMP DECLARE "
    7421              :                              "TARGET with the LOCAL clause, but it has been "
    7422              :                              "specified with a different clause before",
    7423            2 :                              n.com->name, &n.loc);
    7424           23 :             if (n.com->omp_device_type != OMP_DEVICE_TYPE_UNSET
    7425            5 :                 && n.com->omp_device_type != c->device_type)
    7426              :               {
    7427            2 :                 const char *dt = "any";
    7428            2 :                 if (n.com->omp_device_type == OMP_DEVICE_TYPE_HOST)
    7429              :                   dt = "host";
    7430            0 :                 else if (n.com->omp_device_type == OMP_DEVICE_TYPE_NOHOST)
    7431            0 :                   dt = "nohost";
    7432            2 :                 gfc_error_now ("List item %qs at %L set in previous OMP DECLARE"
    7433              :                                " TARGET directive to the different DEVICE_TYPE "
    7434            2 :                                "%qs", n.com->name, &n.loc, dt);
    7435              :               }
    7436           23 :             n.com->omp_declare_target_local = 1;
    7437           23 :             n.com->omp_device_type = c->device_type;
    7438           46 :             for (gfc_symbol *s = n.com->head; s; s = s->common_next)
    7439              :               {
    7440           23 :                 gfc_add_omp_declare_target_local (&s->attr, s->name, &n.loc);
    7441           23 :                 s->attr.omp_device_type = c->device_type;
    7442              :               }
    7443              :           }
    7444           39 :       free (c);
    7445              :     }
    7446              : 
    7447          243 :   if (gfc_match_omp_eos () != MATCH_YES)
    7448              :     {
    7449            0 :       gfc_error ("Unexpected junk after OMP %s at %C",
    7450              :                  is_groupprivate ? "GROUPPRIVATE" : "THREADPRIVATE");
    7451            0 :       goto cleanup;
    7452              :     }
    7453              : 
    7454              :   return MATCH_YES;
    7455              : 
    7456            0 : syntax:
    7457            0 :   gfc_error ("Syntax error in !$OMP %s list at %C",
    7458              :              is_groupprivate ? "GROUPPRIVATE" : "THREADPRIVATE");
    7459              : 
    7460           16 : cleanup:
    7461           16 :   gfc_current_locus = old_loc;
    7462           16 :   return MATCH_ERROR;
    7463          259 : }
    7464              : 
    7465              : 
    7466              : match
    7467           48 : gfc_match_omp_groupprivate (void)
    7468              : {
    7469           48 :   return gfc_match_omp_thread_group_private (true);
    7470              : }
    7471              : 
    7472              : 
    7473              : match
    7474          211 : gfc_match_omp_threadprivate (void)
    7475              : {
    7476          211 :   return gfc_match_omp_thread_group_private (false);
    7477              : }
    7478              : 
    7479              : 
    7480              : match
    7481         2139 : gfc_match_omp_parallel (void)
    7482              : {
    7483         2139 :   return match_omp (EXEC_OMP_PARALLEL, OMP_PARALLEL_CLAUSES);
    7484              : }
    7485              : 
    7486              : 
    7487              : match
    7488         1191 : gfc_match_omp_parallel_do (void)
    7489              : {
    7490         1191 :   return match_omp (EXEC_OMP_PARALLEL_DO,
    7491         1191 :                     (OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES)
    7492         1191 :                     & ~(omp_mask (OMP_CLAUSE_NOWAIT)));
    7493              : }
    7494              : 
    7495              : 
    7496              : match
    7497          298 : gfc_match_omp_parallel_do_simd (void)
    7498              : {
    7499          298 :   return match_omp (EXEC_OMP_PARALLEL_DO_SIMD,
    7500          298 :                     (OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES | OMP_SIMD_CLAUSES)
    7501          298 :                     & ~(omp_mask (OMP_CLAUSE_NOWAIT)));
    7502              : }
    7503              : 
    7504              : 
    7505              : match
    7506           14 : gfc_match_omp_parallel_masked (void)
    7507              : {
    7508           14 :   return match_omp (EXEC_OMP_PARALLEL_MASKED,
    7509           14 :                     OMP_PARALLEL_CLAUSES | OMP_MASKED_CLAUSES);
    7510              : }
    7511              : 
    7512              : match
    7513           10 : gfc_match_omp_parallel_masked_taskloop (void)
    7514              : {
    7515           10 :   return match_omp (EXEC_OMP_PARALLEL_MASKED_TASKLOOP,
    7516           10 :                     (OMP_PARALLEL_CLAUSES | OMP_MASKED_CLAUSES
    7517           10 :                      | OMP_TASKLOOP_CLAUSES)
    7518           10 :                     & ~(omp_mask (OMP_CLAUSE_IN_REDUCTION)));
    7519              : }
    7520              : 
    7521              : match
    7522           13 : gfc_match_omp_parallel_masked_taskloop_simd (void)
    7523              : {
    7524           13 :   return match_omp (EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD,
    7525           13 :                     (OMP_PARALLEL_CLAUSES | OMP_MASKED_CLAUSES
    7526           13 :                      | OMP_TASKLOOP_CLAUSES | OMP_SIMD_CLAUSES)
    7527           13 :                     & ~(omp_mask (OMP_CLAUSE_IN_REDUCTION)));
    7528              : }
    7529              : 
    7530              : match
    7531           14 : gfc_match_omp_parallel_master (void)
    7532              : {
    7533           14 :   gfc_warning (OPT_Wdeprecated_openmp,
    7534              :                "%<master%> construct at %C deprecated since OpenMP 5.1, use "
    7535              :                "%<masked%>");
    7536           14 :   return match_omp (EXEC_OMP_PARALLEL_MASTER, OMP_PARALLEL_CLAUSES);
    7537              : }
    7538              : 
    7539              : match
    7540           15 : gfc_match_omp_parallel_master_taskloop (void)
    7541              : {
    7542           15 :   gfc_warning (OPT_Wdeprecated_openmp,
    7543              :                "%<master%> construct at %C deprecated since OpenMP 5.1, "
    7544              :                "use %<masked%>");
    7545           15 :   return match_omp (EXEC_OMP_PARALLEL_MASTER_TASKLOOP,
    7546           15 :                     (OMP_PARALLEL_CLAUSES | OMP_TASKLOOP_CLAUSES)
    7547           15 :                     & ~(omp_mask (OMP_CLAUSE_IN_REDUCTION)));
    7548              : }
    7549              : 
    7550              : match
    7551           21 : gfc_match_omp_parallel_master_taskloop_simd (void)
    7552              : {
    7553           21 :   gfc_warning (OPT_Wdeprecated_openmp,
    7554              :                "%<master%> construct at %C deprecated since OpenMP 5.1, "
    7555              :                "use %<masked%>");
    7556           21 :   return match_omp (EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD,
    7557           21 :                     (OMP_PARALLEL_CLAUSES | OMP_TASKLOOP_CLAUSES
    7558           21 :                      | OMP_SIMD_CLAUSES)
    7559           21 :                     & ~(omp_mask (OMP_CLAUSE_IN_REDUCTION)));
    7560              : }
    7561              : 
    7562              : match
    7563           59 : gfc_match_omp_parallel_sections (void)
    7564              : {
    7565           59 :   return match_omp (EXEC_OMP_PARALLEL_SECTIONS,
    7566           59 :                     (OMP_PARALLEL_CLAUSES | OMP_SECTIONS_CLAUSES)
    7567           59 :                     & ~(omp_mask (OMP_CLAUSE_NOWAIT)));
    7568              : }
    7569              : 
    7570              : 
    7571              : match
    7572           56 : gfc_match_omp_parallel_workshare (void)
    7573              : {
    7574           56 :   return match_omp (EXEC_OMP_PARALLEL_WORKSHARE, OMP_PARALLEL_CLAUSES);
    7575              : }
    7576              : 
    7577              : void
    7578        48643 : gfc_check_omp_requires (gfc_namespace *ns, int ref_omp_requires)
    7579              : {
    7580        48643 :   const char *msg = G_("Program unit at %L has OpenMP device "
    7581              :                        "constructs/routines but does not set !$OMP REQUIRES %s "
    7582              :                        "but other program units do");
    7583        48643 :   if (ns->omp_target_seen
    7584         1205 :       && (ns->omp_requires & OMP_REQ_TARGET_MASK)
    7585         1205 :          != (ref_omp_requires & OMP_REQ_TARGET_MASK))
    7586              :     {
    7587            6 :       gcc_assert (ns->proc_name);
    7588            6 :       if ((ref_omp_requires & OMP_REQ_REVERSE_OFFLOAD)
    7589            5 :           && !(ns->omp_requires & OMP_REQ_REVERSE_OFFLOAD))
    7590            4 :         gfc_error (msg, &ns->proc_name->declared_at, "REVERSE_OFFLOAD");
    7591            6 :       if ((ref_omp_requires & OMP_REQ_UNIFIED_ADDRESS)
    7592            1 :           && !(ns->omp_requires & OMP_REQ_UNIFIED_ADDRESS))
    7593            1 :         gfc_error (msg, &ns->proc_name->declared_at, "UNIFIED_ADDRESS");
    7594            6 :       if ((ref_omp_requires & OMP_REQ_UNIFIED_SHARED_MEMORY)
    7595            4 :           && !(ns->omp_requires & OMP_REQ_UNIFIED_SHARED_MEMORY))
    7596            2 :         gfc_error (msg, &ns->proc_name->declared_at, "UNIFIED_SHARED_MEMORY");
    7597            6 :       if ((ref_omp_requires & OMP_REQ_SELF_MAPS)
    7598            1 :           && !(ns->omp_requires & OMP_REQ_UNIFIED_SHARED_MEMORY))
    7599            1 :         gfc_error (msg, &ns->proc_name->declared_at, "SELF_MAPS");
    7600              :     }
    7601        48643 : }
    7602              : 
    7603              : bool
    7604          120 : gfc_omp_requires_add_clause (gfc_omp_requires_kind clause,
    7605              :                              const char *clause_name, locus *loc,
    7606              :                              const char *module_name)
    7607              : {
    7608          120 :   gfc_namespace *prog_unit = gfc_current_ns;
    7609          144 :   while (prog_unit->parent)
    7610              :     {
    7611           25 :       if (gfc_state_stack->previous
    7612           25 :           && gfc_state_stack->previous->state == COMP_INTERFACE)
    7613              :         break;
    7614              :       prog_unit = prog_unit->parent;
    7615              :     }
    7616              : 
    7617              :   /* Requires added after use.  */
    7618          120 :   if (prog_unit->omp_target_seen
    7619           24 :       && (clause & OMP_REQ_TARGET_MASK)
    7620           24 :       && !(prog_unit->omp_requires & clause))
    7621              :     {
    7622            0 :       if (module_name)
    7623            0 :         gfc_error ("!$OMP REQUIRES clause %qs specified via module %qs use "
    7624              :                    "at %L comes after using a device construct/routine",
    7625              :                    clause_name, module_name, loc);
    7626              :       else
    7627            0 :         gfc_error ("!$OMP REQUIRES clause %qs specified at %L comes after "
    7628              :                    "using a device construct/routine", clause_name, loc);
    7629            0 :       return false;
    7630              :     }
    7631              : 
    7632              :   /* Overriding atomic_default_mem_order clause value.  */
    7633          120 :   if ((clause & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
    7634           34 :       && (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
    7635            6 :       && (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
    7636            6 :          != (int) clause)
    7637              :     {
    7638            3 :       const char *other;
    7639            3 :       switch (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
    7640              :         {
    7641              :         case OMP_REQ_ATOMIC_MEM_ORDER_SEQ_CST: other = "seq_cst"; break;
    7642            0 :         case OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL: other = "acq_rel"; break;
    7643            1 :         case OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE: other = "acquire"; break;
    7644            1 :         case OMP_REQ_ATOMIC_MEM_ORDER_RELAXED: other = "relaxed"; break;
    7645            0 :         case OMP_REQ_ATOMIC_MEM_ORDER_RELEASE: other = "release"; break;
    7646            0 :         default: gcc_unreachable ();
    7647              :         }
    7648              : 
    7649            3 :       if (module_name)
    7650            0 :         gfc_error ("!$OMP REQUIRES clause %<atomic_default_mem_order(%s)%> "
    7651              :                    "specified via module %qs use at %L overrides a previous "
    7652              :                    "%<atomic_default_mem_order(%s)%> (which might be through "
    7653              :                    "using a module)", clause_name, module_name, loc, other);
    7654              :       else
    7655            3 :         gfc_error ("!$OMP REQUIRES clause %<atomic_default_mem_order(%s)%> "
    7656              :                    "specified at %L overrides a previous "
    7657              :                    "%<atomic_default_mem_order(%s)%> (which might be through "
    7658              :                    "using a module)", clause_name, loc, other);
    7659            3 :       return false;
    7660              :     }
    7661              : 
    7662              :   /* Requires via module not at program-unit level and not repeating clause.  */
    7663          117 :   if (prog_unit != gfc_current_ns && !(prog_unit->omp_requires & clause))
    7664              :     {
    7665            0 :       if (clause & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
    7666            0 :         gfc_error ("!$OMP REQUIRES clause %<atomic_default_mem_order(%s)%> "
    7667              :                    "specified via module %qs use at %L but same clause is "
    7668              :                    "not specified for the program unit", clause_name,
    7669              :                    module_name, loc);
    7670              :       else
    7671            0 :         gfc_error ("!$OMP REQUIRES clause %qs specified via module %qs use at "
    7672              :                    "%L but same clause is not specified for the program unit",
    7673              :                    clause_name, module_name, loc);
    7674            0 :       return false;
    7675              :     }
    7676              : 
    7677          117 :   if (!gfc_state_stack->previous
    7678          109 :       || gfc_state_stack->previous->state != COMP_INTERFACE)
    7679          116 :     prog_unit->omp_requires |= clause;
    7680              :   return true;
    7681              : }
    7682              : 
    7683              : match
    7684           92 : gfc_match_omp_requires (void)
    7685              : {
    7686           92 :   static const char *clauses[] = {"reverse_offload",
    7687              :                                   "unified_address",
    7688              :                                   "unified_shared_memory",
    7689              :                                   "self_maps",
    7690              :                                   "dynamic_allocators",
    7691              :                                   "atomic_default"};
    7692           92 :   const char *clause = NULL;
    7693           92 :   int requires_clauses = 0;
    7694           92 :   bool first = true;
    7695           92 :   locus old_loc;
    7696              : 
    7697           92 :   if (gfc_current_ns->parent
    7698            7 :       && (!gfc_state_stack->previous
    7699            7 :           || gfc_state_stack->previous->state != COMP_INTERFACE))
    7700              :     {
    7701            6 :       gfc_error ("!$OMP REQUIRES at %C must appear in the specification part "
    7702              :                  "of a program unit");
    7703            6 :       return MATCH_ERROR;
    7704              :     }
    7705              : 
    7706          258 :   while (true)
    7707              :     {
    7708          172 :       old_loc = gfc_current_locus;
    7709          172 :       gfc_omp_requires_kind requires_clause;
    7710           86 :       if ((first || gfc_match_char (',') != MATCH_YES)
    7711          172 :           && (first && gfc_match_space () != MATCH_YES))
    7712            0 :         goto error;
    7713          172 :       first = false;
    7714          172 :       gfc_gobble_whitespace ();
    7715          172 :       old_loc = gfc_current_locus;
    7716              : 
    7717          172 :       if (gfc_match_omp_eos () != MATCH_NO)
    7718              :         break;
    7719           97 :       if (gfc_match (clauses[0]) == MATCH_YES)
    7720              :         {
    7721           34 :           clause = clauses[0];
    7722           34 :           requires_clause = OMP_REQ_REVERSE_OFFLOAD;
    7723           34 :           if (requires_clauses & OMP_REQ_REVERSE_OFFLOAD)
    7724            1 :             goto duplicate_clause;
    7725              :         }
    7726           63 :       else if (gfc_match (clauses[1]) == MATCH_YES)
    7727              :         {
    7728            9 :           clause = clauses[1];
    7729            9 :           requires_clause = OMP_REQ_UNIFIED_ADDRESS;
    7730            9 :           if (requires_clauses & OMP_REQ_UNIFIED_ADDRESS)
    7731            1 :             goto duplicate_clause;
    7732              :         }
    7733           54 :       else if (gfc_match (clauses[2]) == MATCH_YES)
    7734              :         {
    7735           14 :           clause = clauses[2];
    7736           14 :           requires_clause = OMP_REQ_UNIFIED_SHARED_MEMORY;
    7737           14 :           if (requires_clauses & OMP_REQ_UNIFIED_SHARED_MEMORY)
    7738            1 :             goto duplicate_clause;
    7739              :         }
    7740           40 :       else if (gfc_match (clauses[3]) == MATCH_YES)
    7741              :         {
    7742            1 :           clause = clauses[3];
    7743            1 :           requires_clause = OMP_REQ_SELF_MAPS;
    7744            1 :           if (requires_clauses & OMP_REQ_SELF_MAPS)
    7745            0 :             goto duplicate_clause;
    7746              :         }
    7747           39 :       else if (gfc_match (clauses[4]) == MATCH_YES)
    7748              :         {
    7749            7 :           clause = clauses[4];
    7750            7 :           requires_clause = OMP_REQ_DYNAMIC_ALLOCATORS;
    7751            7 :           if (requires_clauses & OMP_REQ_DYNAMIC_ALLOCATORS)
    7752            1 :             goto duplicate_clause;
    7753              :         }
    7754           32 :       else if (gfc_match ("atomic_default_mem_order (") == MATCH_YES)
    7755              :         {
    7756           31 :           clause = clauses[5];
    7757           31 :           if (requires_clauses & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
    7758            1 :             goto duplicate_clause;
    7759           30 :           if (gfc_match (" seq_cst )") == MATCH_YES)
    7760              :             {
    7761              :               clause = "seq_cst";
    7762              :               requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_SEQ_CST;
    7763              :             }
    7764           18 :           else if (gfc_match (" acq_rel )") == MATCH_YES)
    7765              :             {
    7766              :               clause = "acq_rel";
    7767              :               requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL;
    7768              :             }
    7769           12 :           else if (gfc_match (" acquire )") == MATCH_YES)
    7770              :             {
    7771              :               clause = "acquire";
    7772              :               requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE;
    7773              :             }
    7774            9 :           else if (gfc_match (" relaxed )") == MATCH_YES)
    7775              :             {
    7776              :               clause = "relaxed";
    7777              :               requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_RELAXED;
    7778              :             }
    7779            5 :           else if (gfc_match (" release )") == MATCH_YES)
    7780              :             {
    7781              :               clause = "release";
    7782              :               requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_RELEASE;
    7783              :             }
    7784              :           else
    7785              :             {
    7786            2 :               gfc_error ("Expected ACQ_REL, ACQUIRE, RELAXED, RELEASE or "
    7787              :                          "SEQ_CST for ATOMIC_DEFAULT_MEM_ORDER clause at %C");
    7788            2 :               goto error;
    7789              :             }
    7790              :         }
    7791              :       else
    7792            1 :         goto error;
    7793              : 
    7794           89 :       if (!gfc_omp_requires_add_clause (requires_clause, clause, &old_loc, NULL))
    7795            3 :         goto error;
    7796           86 :       requires_clauses |= requires_clause;
    7797           86 :     }
    7798              : 
    7799           75 :   if (requires_clauses == 0)
    7800              :     {
    7801            1 :       if (!gfc_error_flag_test ())
    7802            1 :         gfc_error ("Clause expected at %C");
    7803            1 :       goto error;
    7804              :     }
    7805              :   return MATCH_YES;
    7806              : 
    7807            5 : duplicate_clause:
    7808            5 :   gfc_error ("%qs clause at %L specified more than once", clause, &old_loc);
    7809           12 : error:
    7810           12 :   if (!gfc_error_flag_test ())
    7811            1 :     gfc_error ("Expected UNIFIED_ADDRESS, UNIFIED_SHARED_MEMORY, SELF_MAPS, "
    7812              :                "DYNAMIC_ALLOCATORS, REVERSE_OFFLOAD, or "
    7813              :                "ATOMIC_DEFAULT_MEM_ORDER clause at %L", &old_loc);
    7814              :   return MATCH_ERROR;
    7815              : }
    7816              : 
    7817              : 
    7818              : match
    7819           51 : gfc_match_omp_scan (void)
    7820              : {
    7821           51 :   bool incl;
    7822           51 :   gfc_omp_clauses *c = gfc_get_omp_clauses ();
    7823           51 :   gfc_gobble_whitespace ();
    7824           51 :   if ((incl = (gfc_match ("inclusive") == MATCH_YES))
    7825           51 :       || gfc_match ("exclusive") == MATCH_YES)
    7826              :     {
    7827           70 :       if (gfc_match_omp_variable_list (" (", &c->lists[incl ? OMP_LIST_SCAN_IN
    7828              :                                                             : OMP_LIST_SCAN_EX],
    7829              :                                        false) != MATCH_YES)
    7830              :         {
    7831            0 :           gfc_free_omp_clauses (c);
    7832            0 :           return MATCH_ERROR;
    7833              :         }
    7834              :     }
    7835              :   else
    7836              :     {
    7837            1 :       gfc_error ("Expected INCLUSIVE or EXCLUSIVE clause at %C");
    7838            1 :       gfc_free_omp_clauses (c);
    7839            1 :       return MATCH_ERROR;
    7840              :     }
    7841           50 :   if (gfc_match_omp_eos () != MATCH_YES)
    7842              :     {
    7843            1 :       gfc_error ("Unexpected junk after !$OMP SCAN at %C");
    7844            1 :       gfc_free_omp_clauses (c);
    7845            1 :       return MATCH_ERROR;
    7846              :     }
    7847              : 
    7848           49 :   new_st.op = EXEC_OMP_SCAN;
    7849           49 :   new_st.ext.omp_clauses = c;
    7850           49 :   return MATCH_YES;
    7851              : }
    7852              : 
    7853              : 
    7854              : match
    7855           58 : gfc_match_omp_scope (void)
    7856              : {
    7857           58 :   return match_omp (EXEC_OMP_SCOPE, OMP_SCOPE_CLAUSES);
    7858              : }
    7859              : 
    7860              : 
    7861              : match
    7862           82 : gfc_match_omp_sections (void)
    7863              : {
    7864           82 :   return match_omp (EXEC_OMP_SECTIONS, OMP_SECTIONS_CLAUSES);
    7865              : }
    7866              : 
    7867              : 
    7868              : match
    7869          782 : gfc_match_omp_simd (void)
    7870              : {
    7871          782 :   return match_omp (EXEC_OMP_SIMD, OMP_SIMD_CLAUSES);
    7872              : }
    7873              : 
    7874              : 
    7875              : match
    7876          570 : gfc_match_omp_single (void)
    7877              : {
    7878          570 :   return match_omp (EXEC_OMP_SINGLE, OMP_SINGLE_CLAUSES);
    7879              : }
    7880              : 
    7881              : 
    7882              : match
    7883         1970 : gfc_match_omp_target (void)
    7884              : {
    7885         1970 :   return match_omp (EXEC_OMP_TARGET, OMP_TARGET_CLAUSES);
    7886              : }
    7887              : 
    7888              : 
    7889              : match
    7890         1398 : gfc_match_omp_target_data (void)
    7891              : {
    7892         1398 :   return match_omp (EXEC_OMP_TARGET_DATA, OMP_TARGET_DATA_CLAUSES);
    7893              : }
    7894              : 
    7895              : 
    7896              : match
    7897          408 : gfc_match_omp_target_enter_data (void)
    7898              : {
    7899          408 :   return match_omp (EXEC_OMP_TARGET_ENTER_DATA, OMP_TARGET_ENTER_DATA_CLAUSES);
    7900              : }
    7901              : 
    7902              : 
    7903              : match
    7904          322 : gfc_match_omp_target_exit_data (void)
    7905              : {
    7906          322 :   return match_omp (EXEC_OMP_TARGET_EXIT_DATA, OMP_TARGET_EXIT_DATA_CLAUSES);
    7907              : }
    7908              : 
    7909              : 
    7910              : match
    7911           24 : gfc_match_omp_target_parallel (void)
    7912              : {
    7913           24 :   return match_omp (EXEC_OMP_TARGET_PARALLEL,
    7914           24 :                     (OMP_TARGET_CLAUSES | OMP_PARALLEL_CLAUSES)
    7915           24 :                     & ~(omp_mask (OMP_CLAUSE_COPYIN)));
    7916              : }
    7917              : 
    7918              : 
    7919              : match
    7920           81 : gfc_match_omp_target_parallel_do (void)
    7921              : {
    7922           81 :   return match_omp (EXEC_OMP_TARGET_PARALLEL_DO,
    7923           81 :                     (OMP_TARGET_CLAUSES | OMP_PARALLEL_CLAUSES
    7924           81 :                      | OMP_DO_CLAUSES) & ~(omp_mask (OMP_CLAUSE_COPYIN)));
    7925              : }
    7926              : 
    7927              : 
    7928              : match
    7929           19 : gfc_match_omp_target_parallel_do_simd (void)
    7930              : {
    7931           19 :   return match_omp (EXEC_OMP_TARGET_PARALLEL_DO_SIMD,
    7932           19 :                     (OMP_TARGET_CLAUSES | OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES
    7933           19 :                      | OMP_SIMD_CLAUSES) & ~(omp_mask (OMP_CLAUSE_COPYIN)));
    7934              : }
    7935              : 
    7936              : 
    7937              : match
    7938           34 : gfc_match_omp_target_simd (void)
    7939              : {
    7940           34 :   return match_omp (EXEC_OMP_TARGET_SIMD,
    7941           34 :                     OMP_TARGET_CLAUSES | OMP_SIMD_CLAUSES);
    7942              : }
    7943              : 
    7944              : 
    7945              : match
    7946           72 : gfc_match_omp_target_teams (void)
    7947              : {
    7948           72 :   return match_omp (EXEC_OMP_TARGET_TEAMS,
    7949           72 :                     OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES);
    7950              : }
    7951              : 
    7952              : 
    7953              : match
    7954           19 : gfc_match_omp_target_teams_distribute (void)
    7955              : {
    7956           19 :   return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE,
    7957           19 :                     OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
    7958           19 :                     | OMP_DISTRIBUTE_CLAUSES);
    7959              : }
    7960              : 
    7961              : 
    7962              : match
    7963           64 : gfc_match_omp_target_teams_distribute_parallel_do (void)
    7964              : {
    7965           64 :   return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO,
    7966           64 :                     (OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
    7967           64 :                      | OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
    7968           64 :                      | OMP_DO_CLAUSES)
    7969           64 :                     & ~(omp_mask (OMP_CLAUSE_ORDERED))
    7970           64 :                     & ~(omp_mask (OMP_CLAUSE_LINEAR)));
    7971              : }
    7972              : 
    7973              : 
    7974              : match
    7975           35 : gfc_match_omp_target_teams_distribute_parallel_do_simd (void)
    7976              : {
    7977           35 :   return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
    7978           35 :                     (OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
    7979           35 :                      | OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
    7980           35 :                      | OMP_DO_CLAUSES | OMP_SIMD_CLAUSES)
    7981           35 :                     & ~(omp_mask (OMP_CLAUSE_ORDERED)));
    7982              : }
    7983              : 
    7984              : 
    7985              : match
    7986           21 : gfc_match_omp_target_teams_distribute_simd (void)
    7987              : {
    7988           21 :   return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD,
    7989           21 :                     OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
    7990           21 :                     | OMP_DISTRIBUTE_CLAUSES | OMP_SIMD_CLAUSES);
    7991              : }
    7992              : 
    7993              : 
    7994              : match
    7995         1704 : gfc_match_omp_target_update (void)
    7996              : {
    7997         1704 :   return match_omp (EXEC_OMP_TARGET_UPDATE, OMP_TARGET_UPDATE_CLAUSES);
    7998              : }
    7999              : 
    8000              : 
    8001              : match
    8002         1180 : gfc_match_omp_task (void)
    8003              : {
    8004         1180 :   return match_omp (EXEC_OMP_TASK, OMP_TASK_CLAUSES);
    8005              : }
    8006              : 
    8007              : 
    8008              : match
    8009           72 : gfc_match_omp_taskloop (void)
    8010              : {
    8011           72 :   return match_omp (EXEC_OMP_TASKLOOP, OMP_TASKLOOP_CLAUSES);
    8012              : }
    8013              : 
    8014              : 
    8015              : match
    8016           40 : gfc_match_omp_taskloop_simd (void)
    8017              : {
    8018           40 :   return match_omp (EXEC_OMP_TASKLOOP_SIMD,
    8019           40 :                     OMP_TASKLOOP_CLAUSES | OMP_SIMD_CLAUSES);
    8020              : }
    8021              : 
    8022              : 
    8023              : match
    8024          146 : gfc_match_omp_taskwait (void)
    8025              : {
    8026          146 :   if (gfc_match_omp_eos () == MATCH_YES)
    8027              :     {
    8028          133 :       new_st.op = EXEC_OMP_TASKWAIT;
    8029          133 :       new_st.ext.omp_clauses = NULL;
    8030          133 :       return MATCH_YES;
    8031              :     }
    8032           13 :   return match_omp (EXEC_OMP_TASKWAIT,
    8033           13 :                     omp_mask (OMP_CLAUSE_DEPEND) | OMP_CLAUSE_NOWAIT);
    8034              : }
    8035              : 
    8036              : 
    8037              : match
    8038           10 : gfc_match_omp_taskyield (void)
    8039              : {
    8040           10 :   if (gfc_match_omp_eos () != MATCH_YES)
    8041              :     {
    8042            0 :       gfc_error ("Unexpected junk after TASKYIELD clause at %C");
    8043            0 :       return MATCH_ERROR;
    8044              :     }
    8045           10 :   new_st.op = EXEC_OMP_TASKYIELD;
    8046           10 :   new_st.ext.omp_clauses = NULL;
    8047           10 :   return MATCH_YES;
    8048              : }
    8049              : 
    8050              : 
    8051              : match
    8052          150 : gfc_match_omp_teams (void)
    8053              : {
    8054          150 :   return match_omp (EXEC_OMP_TEAMS, OMP_TEAMS_CLAUSES);
    8055              : }
    8056              : 
    8057              : 
    8058              : match
    8059           22 : gfc_match_omp_teams_distribute (void)
    8060              : {
    8061           22 :   return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE,
    8062           22 :                     OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES);
    8063              : }
    8064              : 
    8065              : 
    8066              : match
    8067           39 : gfc_match_omp_teams_distribute_parallel_do (void)
    8068              : {
    8069           39 :   return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO,
    8070           39 :                     (OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES
    8071           39 :                      | OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES)
    8072           39 :                     & ~(omp_mask (OMP_CLAUSE_ORDERED)
    8073           39 :                         | OMP_CLAUSE_LINEAR | OMP_CLAUSE_NOWAIT));
    8074              : }
    8075              : 
    8076              : 
    8077              : match
    8078           62 : gfc_match_omp_teams_distribute_parallel_do_simd (void)
    8079              : {
    8080           62 :   return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
    8081           62 :                     (OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES
    8082           62 :                      | OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES
    8083           62 :                      | OMP_SIMD_CLAUSES)
    8084           62 :                     & ~(omp_mask (OMP_CLAUSE_ORDERED) | OMP_CLAUSE_NOWAIT));
    8085              : }
    8086              : 
    8087              : 
    8088              : match
    8089           44 : gfc_match_omp_teams_distribute_simd (void)
    8090              : {
    8091           44 :   return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE_SIMD,
    8092           44 :                     OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES
    8093           44 :                     | OMP_SIMD_CLAUSES);
    8094              : }
    8095              : 
    8096              : match
    8097          203 : gfc_match_omp_tile (void)
    8098              : {
    8099          203 :   return match_omp (EXEC_OMP_TILE, OMP_TILE_CLAUSES);
    8100              : }
    8101              : 
    8102              : match
    8103          415 : gfc_match_omp_unroll (void)
    8104              : {
    8105          415 :   return match_omp (EXEC_OMP_UNROLL, OMP_UNROLL_CLAUSES);
    8106              : }
    8107              : 
    8108              : match
    8109           39 : gfc_match_omp_workshare (void)
    8110              : {
    8111           39 :   return match_omp (EXEC_OMP_WORKSHARE, OMP_WORKSHARE_CLAUSES);
    8112              : }
    8113              : 
    8114              : 
    8115              : match
    8116           49 : gfc_match_omp_masked (void)
    8117              : {
    8118           49 :   return match_omp (EXEC_OMP_MASKED, OMP_MASKED_CLAUSES);
    8119              : }
    8120              : 
    8121              : match
    8122           10 : gfc_match_omp_masked_taskloop (void)
    8123              : {
    8124           10 :   return match_omp (EXEC_OMP_MASKED_TASKLOOP,
    8125           10 :                     OMP_MASKED_CLAUSES | OMP_TASKLOOP_CLAUSES);
    8126              : }
    8127              : 
    8128              : match
    8129           16 : gfc_match_omp_masked_taskloop_simd (void)
    8130              : {
    8131           16 :   return match_omp (EXEC_OMP_MASKED_TASKLOOP_SIMD,
    8132           16 :                     (OMP_MASKED_CLAUSES | OMP_TASKLOOP_CLAUSES
    8133           16 :                      | OMP_SIMD_CLAUSES));
    8134              : }
    8135              : 
    8136              : match
    8137          111 : gfc_match_omp_master (void)
    8138              : {
    8139          111 :   gfc_warning (OPT_Wdeprecated_openmp,
    8140              :                "%<master%> construct at %C deprecated since OpenMP 5.1, "
    8141              :                "use %<masked%>");
    8142          111 :   if (gfc_match_omp_eos () != MATCH_YES)
    8143              :     {
    8144            1 :       gfc_error ("Unexpected junk after $OMP MASTER statement at %C");
    8145            1 :       return MATCH_ERROR;
    8146              :     }
    8147          110 :   new_st.op = EXEC_OMP_MASTER;
    8148          110 :   new_st.ext.omp_clauses = NULL;
    8149          110 :   return MATCH_YES;
    8150              : }
    8151              : 
    8152              : match
    8153           16 : gfc_match_omp_master_taskloop (void)
    8154              : {
    8155           16 :   gfc_warning (OPT_Wdeprecated_openmp,
    8156              :                "%<master%> construct at %C deprecated since OpenMP 5.1, "
    8157              :                "use %<masked%>");
    8158           16 :   return match_omp (EXEC_OMP_MASTER_TASKLOOP, OMP_TASKLOOP_CLAUSES);
    8159              : }
    8160              : 
    8161              : match
    8162           21 : gfc_match_omp_master_taskloop_simd (void)
    8163              : {
    8164           21 :   gfc_warning (OPT_Wdeprecated_openmp,
    8165              :                "%<master%> construct at %C deprecated since OpenMP 5.1, use "
    8166              :                "%<masked%>");
    8167           21 :   return match_omp (EXEC_OMP_MASTER_TASKLOOP_SIMD,
    8168           21 :                     OMP_TASKLOOP_CLAUSES | OMP_SIMD_CLAUSES);
    8169              : }
    8170              : 
    8171              : match
    8172          235 : gfc_match_omp_ordered (void)
    8173              : {
    8174          235 :   return match_omp (EXEC_OMP_ORDERED, OMP_ORDERED_CLAUSES);
    8175              : }
    8176              : 
    8177              : match
    8178           24 : gfc_match_omp_nothing (void)
    8179              : {
    8180           24 :   if (gfc_match_omp_eos () != MATCH_YES)
    8181              :     {
    8182            1 :       gfc_error ("Unexpected junk after $OMP NOTHING statement at %C");
    8183            1 :       return MATCH_ERROR;
    8184              :     }
    8185              :   /* Will use ST_NONE; therefore, no EXEC_OMP_ is needed.  */
    8186              :   return MATCH_YES;
    8187              : }
    8188              : 
    8189              : match
    8190          317 : gfc_match_omp_ordered_depend (void)
    8191              : {
    8192          317 :   return match_omp (EXEC_OMP_ORDERED, omp_mask (OMP_CLAUSE_DOACROSS));
    8193              : }
    8194              : 
    8195              : 
    8196              : /* omp atomic [clause-list]
    8197              :    - atomic-clause:  read | write | update
    8198              :    - capture
    8199              :    - memory-order-clause: seq_cst | acq_rel | release | acquire | relaxed
    8200              :    - hint(hint-expr)
    8201              :    - OpenMP 5.1: compare | fail (seq_cst | acquire | relaxed ) | weak
    8202              : */
    8203              : 
    8204              : match
    8205         2171 : gfc_match_omp_atomic (void)
    8206              : {
    8207         2171 :   gfc_omp_clauses *c;
    8208         2171 :   locus loc = gfc_current_locus;
    8209              : 
    8210         2171 :   if (gfc_match_omp_clauses (&c, OMP_ATOMIC_CLAUSES, true, true) != MATCH_YES)
    8211              :     return MATCH_ERROR;
    8212              : 
    8213         2153 :   if (c->atomic_op == GFC_OMP_ATOMIC_UNSET)
    8214         1011 :     c->atomic_op = GFC_OMP_ATOMIC_UPDATE;
    8215              : 
    8216         2153 :   if (c->capture && c->atomic_op != GFC_OMP_ATOMIC_UPDATE)
    8217            3 :     gfc_error ("!$OMP ATOMIC at %L with %s clause is incompatible with "
    8218              :                "READ or WRITE", &loc, "CAPTURE");
    8219         2153 :   if (c->compare && c->atomic_op != GFC_OMP_ATOMIC_UPDATE)
    8220            3 :     gfc_error ("!$OMP ATOMIC at %L with %s clause is incompatible with "
    8221              :                "READ or WRITE", &loc, "COMPARE");
    8222         2153 :   if (c->fail != OMP_MEMORDER_UNSET && c->atomic_op != GFC_OMP_ATOMIC_UPDATE)
    8223            2 :     gfc_error ("!$OMP ATOMIC at %L with %s clause is incompatible with "
    8224              :                "READ or WRITE", &loc, "FAIL");
    8225         2153 :   if (c->weak && !c->compare)
    8226              :     {
    8227            5 :       gfc_error ("!$OMP ATOMIC at %L with %s clause requires %s clause", &loc,
    8228              :                  "WEAK", "COMPARE");
    8229            5 :       c->weak = false;
    8230              :     }
    8231              : 
    8232         2153 :   if (c->memorder == OMP_MEMORDER_UNSET)
    8233              :     {
    8234         1969 :       gfc_namespace *prog_unit = gfc_current_ns;
    8235         2525 :       while (prog_unit->parent)
    8236              :         prog_unit = prog_unit->parent;
    8237         1969 :       switch (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
    8238              :         {
    8239         1936 :         case 0:
    8240         1936 :         case OMP_REQ_ATOMIC_MEM_ORDER_RELAXED:
    8241         1936 :           c->memorder = OMP_MEMORDER_RELAXED;
    8242         1936 :           break;
    8243            7 :         case OMP_REQ_ATOMIC_MEM_ORDER_SEQ_CST:
    8244            7 :           c->memorder = OMP_MEMORDER_SEQ_CST;
    8245            7 :           break;
    8246           16 :         case OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL:
    8247           16 :           if (c->capture)
    8248            5 :             c->memorder = OMP_MEMORDER_ACQ_REL;
    8249           11 :           else if (c->atomic_op == GFC_OMP_ATOMIC_READ)
    8250            3 :             c->memorder = OMP_MEMORDER_ACQUIRE;
    8251              :           else
    8252            8 :             c->memorder = OMP_MEMORDER_RELEASE;
    8253              :           break;
    8254            5 :         case OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE:
    8255            5 :           if (c->atomic_op == GFC_OMP_ATOMIC_WRITE)
    8256              :             {
    8257            1 :               gfc_error ("!$OMP ATOMIC WRITE at %L incompatible with "
    8258              :                          "ACQUIRES clause implicitly provided by a "
    8259              :                          "REQUIRES directive", &loc);
    8260            1 :               c->memorder = OMP_MEMORDER_SEQ_CST;
    8261              :             }
    8262              :           else
    8263            4 :             c->memorder = OMP_MEMORDER_ACQUIRE;
    8264              :           break;
    8265            5 :         case OMP_REQ_ATOMIC_MEM_ORDER_RELEASE:
    8266            5 :           if (c->atomic_op == GFC_OMP_ATOMIC_READ)
    8267              :             {
    8268            1 :               gfc_error ("!$OMP ATOMIC READ at %L incompatible with "
    8269              :                          "RELEASE clause implicitly provided by a "
    8270              :                          "REQUIRES directive", &loc);
    8271            1 :               c->memorder = OMP_MEMORDER_SEQ_CST;
    8272              :             }
    8273              :           else
    8274            4 :             c->memorder = OMP_MEMORDER_RELEASE;
    8275              :           break;
    8276            0 :         default:
    8277            0 :           gcc_unreachable ();
    8278              :         }
    8279              :     }
    8280              :   else
    8281          184 :     switch (c->atomic_op)
    8282              :       {
    8283           29 :       case GFC_OMP_ATOMIC_READ:
    8284           29 :         if (c->memorder == OMP_MEMORDER_RELEASE)
    8285              :           {
    8286            1 :             gfc_error ("!$OMP ATOMIC READ at %L incompatible with "
    8287              :                        "RELEASE clause", &loc);
    8288            1 :             c->memorder = OMP_MEMORDER_SEQ_CST;
    8289              :           }
    8290           28 :         else if (c->memorder == OMP_MEMORDER_ACQ_REL)
    8291            1 :           c->memorder = OMP_MEMORDER_ACQUIRE;
    8292              :         break;
    8293           35 :       case GFC_OMP_ATOMIC_WRITE:
    8294           35 :         if (c->memorder == OMP_MEMORDER_ACQUIRE)
    8295              :           {
    8296            1 :             gfc_error ("!$OMP ATOMIC WRITE at %L incompatible with "
    8297              :                        "ACQUIRE clause", &loc);
    8298            1 :             c->memorder = OMP_MEMORDER_SEQ_CST;
    8299              :           }
    8300           34 :         else if (c->memorder == OMP_MEMORDER_ACQ_REL)
    8301            1 :           c->memorder = OMP_MEMORDER_RELEASE;
    8302              :         break;
    8303              :       default:
    8304              :         break;
    8305              :       }
    8306         2153 :   gfc_error_check ();
    8307         2153 :   new_st.ext.omp_clauses = c;
    8308         2153 :   new_st.op = EXEC_OMP_ATOMIC;
    8309         2153 :   return MATCH_YES;
    8310              : }
    8311              : 
    8312              : 
    8313              : /* acc atomic [ read | write | update | capture]  */
    8314              : 
    8315              : match
    8316          552 : gfc_match_oacc_atomic (void)
    8317              : {
    8318          552 :   gfc_omp_clauses *c = gfc_get_omp_clauses ();
    8319          552 :   c->atomic_op = GFC_OMP_ATOMIC_UPDATE;
    8320          552 :   c->memorder = OMP_MEMORDER_RELAXED;
    8321          552 :   gfc_gobble_whitespace ();
    8322          552 :   if (gfc_match ("update") == MATCH_YES)
    8323              :     ;
    8324          373 :   else if (gfc_match ("read") == MATCH_YES)
    8325           17 :     c->atomic_op = GFC_OMP_ATOMIC_READ;
    8326          356 :   else if (gfc_match ("write") == MATCH_YES)
    8327           13 :     c->atomic_op = GFC_OMP_ATOMIC_WRITE;
    8328          343 :   else if (gfc_match ("capture") == MATCH_YES)
    8329          319 :     c->capture = true;
    8330          552 :   gfc_gobble_whitespace ();
    8331          552 :   if (gfc_match_omp_eos () != MATCH_YES)
    8332              :     {
    8333            9 :       gfc_error ("Unexpected junk after !$ACC ATOMIC statement at %C");
    8334            9 :       gfc_free_omp_clauses (c);
    8335            9 :       return MATCH_ERROR;
    8336              :     }
    8337          543 :   new_st.ext.omp_clauses = c;
    8338          543 :   new_st.op = EXEC_OACC_ATOMIC;
    8339          543 :   return MATCH_YES;
    8340              : }
    8341              : 
    8342              : 
    8343              : match
    8344          614 : gfc_match_omp_barrier (void)
    8345              : {
    8346          614 :   if (gfc_match_omp_eos () != MATCH_YES)
    8347              :     {
    8348            0 :       gfc_error ("Unexpected junk after $OMP BARRIER statement at %C");
    8349            0 :       return MATCH_ERROR;
    8350              :     }
    8351          614 :   new_st.op = EXEC_OMP_BARRIER;
    8352          614 :   new_st.ext.omp_clauses = NULL;
    8353          614 :   return MATCH_YES;
    8354              : }
    8355              : 
    8356              : 
    8357              : match
    8358          188 : gfc_match_omp_taskgroup (void)
    8359              : {
    8360          188 :   return match_omp (EXEC_OMP_TASKGROUP, OMP_TASKGROUP_CLAUSES);
    8361              : }
    8362              : 
    8363              : 
    8364              : static enum gfc_omp_cancel_kind
    8365          494 : gfc_match_omp_cancel_kind (void)
    8366              : {
    8367          494 :   if (gfc_match_space () != MATCH_YES)
    8368              :     return OMP_CANCEL_UNKNOWN;
    8369          492 :   if (gfc_match ("parallel") == MATCH_YES)
    8370              :     return OMP_CANCEL_PARALLEL;
    8371          352 :   if (gfc_match ("sections") == MATCH_YES)
    8372              :     return OMP_CANCEL_SECTIONS;
    8373          253 :   if (gfc_match ("do") == MATCH_YES)
    8374              :     return OMP_CANCEL_DO;
    8375          123 :   if (gfc_match ("taskgroup") == MATCH_YES)
    8376              :     return OMP_CANCEL_TASKGROUP;
    8377              :   return OMP_CANCEL_UNKNOWN;
    8378              : }
    8379              : 
    8380              : 
    8381              : match
    8382          321 : gfc_match_omp_cancel (void)
    8383              : {
    8384          321 :   gfc_omp_clauses *c;
    8385          321 :   enum gfc_omp_cancel_kind kind = gfc_match_omp_cancel_kind ();
    8386          321 :   if (kind == OMP_CANCEL_UNKNOWN)
    8387              :     return MATCH_ERROR;
    8388          319 :   if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_IF), false) != MATCH_YES)
    8389              :     return MATCH_ERROR;
    8390          316 :   c->cancel = kind;
    8391          316 :   new_st.op = EXEC_OMP_CANCEL;
    8392          316 :   new_st.ext.omp_clauses = c;
    8393          316 :   return MATCH_YES;
    8394              : }
    8395              : 
    8396              : 
    8397              : match
    8398          173 : gfc_match_omp_cancellation_point (void)
    8399              : {
    8400          173 :   gfc_omp_clauses *c;
    8401          173 :   enum gfc_omp_cancel_kind kind = gfc_match_omp_cancel_kind ();
    8402          173 :   if (kind == OMP_CANCEL_UNKNOWN)
    8403              :     {
    8404            2 :       gfc_error ("Expected construct-type PARALLEL, SECTIONS, DO or TASKGROUP "
    8405              :                  "in $OMP CANCELLATION POINT statement at %C");
    8406            2 :       return MATCH_ERROR;
    8407              :     }
    8408          171 :   if (gfc_match_omp_eos () != MATCH_YES)
    8409              :     {
    8410            0 :       gfc_error ("Unexpected junk after $OMP CANCELLATION POINT statement "
    8411              :                  "at %C");
    8412            0 :       return MATCH_ERROR;
    8413              :     }
    8414          171 :   c = gfc_get_omp_clauses ();
    8415          171 :   c->cancel = kind;
    8416          171 :   new_st.op = EXEC_OMP_CANCELLATION_POINT;
    8417          171 :   new_st.ext.omp_clauses = c;
    8418          171 :   return MATCH_YES;
    8419              : }
    8420              : 
    8421              : 
    8422              : match
    8423         2479 : gfc_match_omp_end_nowait (void)
    8424              : {
    8425         2479 :   bool nowait = false;
    8426         2479 :   if (gfc_match ("% nowait") == MATCH_YES)
    8427          258 :     nowait = true;
    8428         2479 :   if (gfc_match_omp_eos () != MATCH_YES)
    8429              :     {
    8430            4 :       if (nowait)
    8431            3 :         gfc_error ("Unexpected junk after NOWAIT clause at %C");
    8432              :       else
    8433            1 :         gfc_error ("Unexpected junk at %C");
    8434            4 :       return MATCH_ERROR;
    8435              :     }
    8436         2475 :   new_st.op = EXEC_OMP_END_NOWAIT;
    8437         2475 :   new_st.ext.omp_bool = nowait;
    8438         2475 :   return MATCH_YES;
    8439              : }
    8440              : 
    8441              : 
    8442              : match
    8443          566 : gfc_match_omp_end_single (void)
    8444              : {
    8445          566 :   gfc_omp_clauses *c;
    8446          566 :   if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_COPYPRIVATE)
    8447              :                                            | OMP_CLAUSE_NOWAIT) != MATCH_YES)
    8448              :     return MATCH_ERROR;
    8449          566 :   new_st.op = EXEC_OMP_END_SINGLE;
    8450          566 :   new_st.ext.omp_clauses = c;
    8451          566 :   return MATCH_YES;
    8452              : }
    8453              : 
    8454              : 
    8455              : static bool
    8456        37004 : oacc_is_loop (gfc_code *code)
    8457              : {
    8458        37004 :   return code->op == EXEC_OACC_PARALLEL_LOOP
    8459              :          || code->op == EXEC_OACC_KERNELS_LOOP
    8460        19955 :          || code->op == EXEC_OACC_SERIAL_LOOP
    8461        13451 :          || code->op == EXEC_OACC_LOOP;
    8462              : }
    8463              : 
    8464              : static void
    8465         5713 : resolve_scalar_int_expr (gfc_expr *expr, const char *clause)
    8466              : {
    8467         5713 :   if (!gfc_resolve_expr (expr)
    8468         5713 :       || expr->ts.type != BT_INTEGER
    8469        11355 :       || expr->rank != 0)
    8470           89 :     gfc_error ("%s clause at %L requires a scalar INTEGER expression",
    8471              :                clause, &expr->where);
    8472         5713 : }
    8473              : 
    8474              : static void
    8475         3928 : resolve_positive_int_expr (gfc_expr *expr, const char *clause)
    8476              : {
    8477         3928 :   resolve_scalar_int_expr (expr, clause);
    8478         3928 :   if (expr->expr_type == EXPR_CONSTANT
    8479         3507 :       && expr->ts.type == BT_INTEGER
    8480         3474 :       && mpz_sgn (expr->value.integer) <= 0)
    8481           54 :     gfc_warning ((flag_openmp || flag_openmp_simd) ? OPT_Wopenmp : 0,
    8482              :                  "INTEGER expression of %s clause at %L must be positive",
    8483              :                  clause, &expr->where);
    8484         3928 : }
    8485              : 
    8486              : static void
    8487           86 : resolve_nonnegative_int_expr (gfc_expr *expr, const char *clause)
    8488              : {
    8489           86 :   resolve_scalar_int_expr (expr, clause);
    8490           86 :   if (expr->expr_type == EXPR_CONSTANT
    8491           13 :       && expr->ts.type == BT_INTEGER
    8492           11 :       && mpz_sgn (expr->value.integer) < 0)
    8493            6 :     gfc_warning ((flag_openmp || flag_openmp_simd) ? OPT_Wopenmp : 0,
    8494              :                  "INTEGER expression of %s clause at %L must be non-negative",
    8495              :                  clause, &expr->where);
    8496           86 : }
    8497              : 
    8498              : /* Emits error when symbol is pointer, cray pointer or cray pointee
    8499              :    of derived of polymorphic type.  */
    8500              : 
    8501              : static void
    8502           98 : check_symbol_not_pointer (gfc_symbol *sym, locus loc, const char *name)
    8503              : {
    8504           98 :   if (sym->ts.type == BT_DERIVED && sym->attr.cray_pointer)
    8505            0 :     gfc_error ("Cray pointer object %qs of derived type in %s clause at %L",
    8506              :                sym->name, name, &loc);
    8507           98 :   if (sym->ts.type == BT_DERIVED && sym->attr.cray_pointee)
    8508            0 :     gfc_error ("Cray pointee object %qs of derived type in %s clause at %L",
    8509              :                sym->name, name, &loc);
    8510              : 
    8511           98 :   if ((sym->ts.type == BT_ASSUMED && sym->attr.pointer)
    8512           98 :       || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
    8513            0 :           && CLASS_DATA (sym)->attr.pointer))
    8514            0 :     gfc_error ("POINTER object %qs of polymorphic type in %s clause at %L",
    8515              :                sym->name, name, &loc);
    8516           98 :   if ((sym->ts.type == BT_ASSUMED && sym->attr.cray_pointer)
    8517           98 :       || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
    8518            0 :           && CLASS_DATA (sym)->attr.cray_pointer))
    8519            0 :     gfc_error ("Cray pointer object %qs of polymorphic type in %s clause at %L",
    8520              :                sym->name, name, &loc);
    8521           98 :   if ((sym->ts.type == BT_ASSUMED && sym->attr.cray_pointee)
    8522           98 :       || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
    8523            0 :           && CLASS_DATA (sym)->attr.cray_pointee))
    8524            0 :     gfc_error ("Cray pointee object %qs of polymorphic type in %s clause at %L",
    8525              :                sym->name, name, &loc);
    8526           98 : }
    8527              : 
    8528              : /* Emits error when symbol represents assumed size/rank array.  */
    8529              : 
    8530              : static void
    8531        14831 : check_array_not_assumed (gfc_symbol *sym, locus loc, const char *name)
    8532              : {
    8533        14831 :   if (sym->as && sym->as->type == AS_ASSUMED_SIZE)
    8534           13 :     gfc_error ("Assumed size array %qs in %s clause at %L",
    8535              :                sym->name, name, &loc);
    8536        14831 :   if (sym->as && sym->as->type == AS_ASSUMED_RANK)
    8537           11 :     gfc_error ("Assumed rank array %qs in %s clause at %L",
    8538              :                sym->name, name, &loc);
    8539        14831 : }
    8540              : 
    8541              : static void
    8542         5841 : resolve_oacc_data_clauses (gfc_symbol *sym, locus loc, const char *name)
    8543              : {
    8544            0 :   check_array_not_assumed (sym, loc, name);
    8545            0 : }
    8546              : 
    8547              : static void
    8548           65 : resolve_oacc_deviceptr_clause (gfc_symbol *sym, locus loc, const char *name)
    8549              : {
    8550           65 :   if (sym->attr.pointer
    8551           64 :       || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
    8552            0 :           && CLASS_DATA (sym)->attr.class_pointer))
    8553            1 :     gfc_error ("POINTER object %qs in %s clause at %L",
    8554              :                sym->name, name, &loc);
    8555           65 :   if (sym->attr.cray_pointer
    8556           63 :       || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
    8557            0 :           && CLASS_DATA (sym)->attr.cray_pointer))
    8558            2 :     gfc_error ("Cray pointer object %qs in %s clause at %L",
    8559              :                sym->name, name, &loc);
    8560           65 :   if (sym->attr.cray_pointee
    8561           63 :       || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
    8562            0 :           && CLASS_DATA (sym)->attr.cray_pointee))
    8563            2 :     gfc_error ("Cray pointee object %qs in %s clause at %L",
    8564              :                sym->name, name, &loc);
    8565           65 :   if (sym->attr.allocatable
    8566           64 :       || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
    8567            0 :           && CLASS_DATA (sym)->attr.allocatable))
    8568            1 :     gfc_error ("ALLOCATABLE object %qs in %s clause at %L",
    8569              :                sym->name, name, &loc);
    8570           65 :   if (sym->attr.value)
    8571            1 :     gfc_error ("VALUE object %qs in %s clause at %L",
    8572              :                sym->name, name, &loc);
    8573           65 :   check_array_not_assumed (sym, loc, name);
    8574           65 : }
    8575              : 
    8576              : 
    8577              : struct resolve_omp_udr_callback_data
    8578              : {
    8579              :   gfc_symbol *sym1, *sym2;
    8580              : };
    8581              : 
    8582              : 
    8583              : static int
    8584         1413 : resolve_omp_udr_callback (gfc_expr **e, int *, void *data)
    8585              : {
    8586         1413 :   struct resolve_omp_udr_callback_data *rcd
    8587              :     = (struct resolve_omp_udr_callback_data *) data;
    8588         1413 :   if ((*e)->expr_type == EXPR_VARIABLE
    8589          801 :       && ((*e)->symtree->n.sym == rcd->sym1
    8590          255 :           || (*e)->symtree->n.sym == rcd->sym2))
    8591              :     {
    8592          801 :       gfc_ref *ref = gfc_get_ref ();
    8593          801 :       ref->type = REF_ARRAY;
    8594          801 :       ref->u.ar.where = (*e)->where;
    8595          801 :       ref->u.ar.as = (*e)->symtree->n.sym->as;
    8596          801 :       ref->u.ar.type = AR_FULL;
    8597          801 :       ref->u.ar.dimen = 0;
    8598          801 :       ref->next = (*e)->ref;
    8599          801 :       (*e)->ref = ref;
    8600              :     }
    8601         1413 :   return 0;
    8602              : }
    8603              : 
    8604              : 
    8605              : static int
    8606         2990 : resolve_omp_udr_callback2 (gfc_expr **e, int *, void *)
    8607              : {
    8608         2990 :   if ((*e)->expr_type == EXPR_FUNCTION
    8609          360 :       && (*e)->value.function.isym == NULL)
    8610              :     {
    8611          174 :       gfc_symbol *sym = (*e)->symtree->n.sym;
    8612          174 :       if (!sym->attr.intrinsic
    8613          174 :           && sym->attr.if_source == IFSRC_UNKNOWN)
    8614            4 :         gfc_error ("Implicitly declared function %s used in "
    8615              :                    "!$OMP DECLARE REDUCTION at %L", sym->name, &(*e)->where);
    8616              :     }
    8617         2990 :   return 0;
    8618              : }
    8619              : 
    8620              : 
    8621              : static gfc_code *
    8622          797 : resolve_omp_udr_clause (gfc_omp_namelist *n, gfc_namespace *ns,
    8623              :                         gfc_symbol *sym1, gfc_symbol *sym2)
    8624              : {
    8625          797 :   gfc_code *copy;
    8626          797 :   gfc_symbol sym1_copy, sym2_copy;
    8627              : 
    8628          797 :   if (ns->code->op == EXEC_ASSIGN)
    8629              :     {
    8630          625 :       copy = gfc_get_code (EXEC_ASSIGN);
    8631          625 :       copy->expr1 = gfc_copy_expr (ns->code->expr1);
    8632          625 :       copy->expr2 = gfc_copy_expr (ns->code->expr2);
    8633              :     }
    8634              :   else
    8635              :     {
    8636          172 :       copy = gfc_get_code (EXEC_CALL);
    8637          172 :       copy->symtree = ns->code->symtree;
    8638          172 :       copy->ext.actual = gfc_copy_actual_arglist (ns->code->ext.actual);
    8639              :     }
    8640          797 :   copy->loc = ns->code->loc;
    8641          797 :   sym1_copy = *sym1;
    8642          797 :   sym2_copy = *sym2;
    8643          797 :   *sym1 = *n->sym;
    8644          797 :   *sym2 = *n->sym;
    8645          797 :   sym1->name = sym1_copy.name;
    8646          797 :   sym2->name = sym2_copy.name;
    8647          797 :   ns->proc_name = ns->parent->proc_name;
    8648          797 :   if (n->sym->attr.dimension)
    8649              :     {
    8650          348 :       struct resolve_omp_udr_callback_data rcd;
    8651          348 :       rcd.sym1 = sym1;
    8652          348 :       rcd.sym2 = sym2;
    8653          348 :       gfc_code_walker (&copy, gfc_dummy_code_callback,
    8654              :                        resolve_omp_udr_callback, &rcd);
    8655              :     }
    8656          797 :   gfc_resolve_code (copy, gfc_current_ns);
    8657          797 :   if (copy->op == EXEC_CALL && copy->resolved_isym == NULL)
    8658              :     {
    8659          172 :       gfc_symbol *sym = copy->resolved_sym;
    8660          172 :       if (sym
    8661          170 :           && !sym->attr.intrinsic
    8662          170 :           && sym->attr.if_source == IFSRC_UNKNOWN)
    8663            4 :         gfc_error ("Implicitly declared subroutine %s used in "
    8664              :                    "!$OMP DECLARE REDUCTION at %L", sym->name,
    8665              :                    &copy->loc);
    8666              :     }
    8667          797 :   gfc_code_walker (&copy, gfc_dummy_code_callback,
    8668              :                    resolve_omp_udr_callback2, NULL);
    8669          797 :   *sym1 = sym1_copy;
    8670          797 :   *sym2 = sym2_copy;
    8671          797 :   return copy;
    8672              : }
    8673              : 
    8674              : /* Assume that a constant expression in the range 1 (omp_default_mem_alloc)
    8675              :    to GOMP_OMP_PREDEF_ALLOC_MAX, or GOMP_OMPX_PREDEF_ALLOC_MIN to
    8676              :    GOMP_OMPX_PREDEF_ALLOC_MAX is fine.  The original symbol name is already
    8677              :    lost during matching via gfc_match_expr.  */
    8678              : static bool
    8679          130 : is_predefined_allocator (gfc_expr *expr)
    8680              : {
    8681          130 :   return (gfc_resolve_expr (expr)
    8682          129 :           && expr->rank == 0
    8683          124 :           && expr->ts.type == BT_INTEGER
    8684          119 :           && expr->ts.kind == gfc_c_intptr_kind
    8685          114 :           && expr->expr_type == EXPR_CONSTANT
    8686          239 :           && ((mpz_sgn (expr->value.integer) > 0
    8687          107 :                && mpz_cmp_si (expr->value.integer,
    8688              :                               GOMP_OMP_PREDEF_ALLOC_MAX) <= 0)
    8689            4 :               || (mpz_cmp_si (expr->value.integer,
    8690              :                               GOMP_OMPX_PREDEF_ALLOC_MIN) >= 0
    8691            1 :                   && mpz_cmp_si (expr->value.integer,
    8692          130 :                                  GOMP_OMPX_PREDEF_ALLOC_MAX) <= 0)));
    8693              : }
    8694              : 
    8695              : /* Resolve declarative ALLOCATE statement. Note: Common block vars only appear
    8696              :    as /block/ not individual, which is ensured during parsing.  */
    8697              : 
    8698              : void
    8699           62 : gfc_resolve_omp_allocate (gfc_namespace *ns, gfc_omp_namelist *list)
    8700              : {
    8701          278 :   for (gfc_omp_namelist *n = list; n; n = n->next)
    8702              :     {
    8703          216 :       if (n->sym->attr.result || n->sym->result == n->sym)
    8704              :         {
    8705            1 :           gfc_error ("Unexpected function-result variable %qs at %L in "
    8706              :                      "declarative !$OMP ALLOCATE", n->sym->name, &n->where);
    8707           31 :           continue;
    8708              :         }
    8709          215 :       if (ns->omp_allocate->sym->attr.proc_pointer)
    8710              :         {
    8711            0 :           gfc_error ("Procedure pointer %qs not supported with !$OMP "
    8712              :                      "ALLOCATE at %L", n->sym->name, &n->where);
    8713            0 :           continue;
    8714              :         }
    8715          215 :       if (n->sym->attr.flavor != FL_VARIABLE)
    8716              :         {
    8717            3 :           gfc_error ("Argument %qs at %L to declarative !$OMP ALLOCATE "
    8718              :                      "directive must be a variable", n->sym->name,
    8719              :                      &n->where);
    8720            3 :           continue;
    8721              :         }
    8722          212 :       if (ns != n->sym->ns || n->sym->attr.use_assoc || n->sym->attr.imported)
    8723              :         {
    8724            8 :           gfc_error ("Argument %qs at %L to declarative !$OMP ALLOCATE shall be"
    8725              :                      " in the same scope as the variable declaration",
    8726              :                      n->sym->name, &n->where);
    8727            8 :           continue;
    8728              :         }
    8729          204 :       if (n->sym->attr.dummy)
    8730              :         {
    8731            3 :           gfc_error ("Unexpected dummy argument %qs as argument at %L to "
    8732              :                      "declarative !$OMP ALLOCATE", n->sym->name, &n->where);
    8733            3 :           continue;
    8734              :         }
    8735          201 :       if (n->sym->attr.codimension)
    8736              :         {
    8737            0 :           gfc_error ("Unexpected coarray argument %qs as argument at %L to "
    8738              :                      "declarative !$OMP ALLOCATE", n->sym->name, &n->where);
    8739            0 :           continue;
    8740              :         }
    8741          201 :       if (n->sym->attr.omp_allocate)
    8742              :         {
    8743            5 :           if (n->sym->attr.in_common)
    8744              :             {
    8745            1 :               gfc_error ("Duplicated common block %</%s/%> in !$OMP ALLOCATE "
    8746            1 :                          "at %L", n->sym->common_head->name, &n->where);
    8747            3 :               while (n->next && n->next->sym
    8748            3 :                      && n->sym->common_head == n->next->sym->common_head)
    8749              :                 n = n->next;
    8750              :             }
    8751              :           else
    8752            4 :             gfc_error ("Duplicated variable %qs in !$OMP ALLOCATE at %L",
    8753              :                        n->sym->name, &n->where);
    8754            5 :           continue;
    8755              :         }
    8756              :       /* For 'equivalence(a,b)', a 'union_type {<type> a,b} equiv.0' is created
    8757              :          with a value expression for 'a' as 'equiv.0.a' (likewise for b); while
    8758              :          this can be handled, EQUIVALENCE is marked as obsolescent since Fortran
    8759              :          2018 and also not widely used.  However, it could be supported,
    8760              :          if needed. */
    8761          196 :       if (n->sym->attr.in_equivalence)
    8762              :         {
    8763            2 :           gfc_error ("Sorry, EQUIVALENCE object %qs not supported with !$OMP "
    8764              :                      "ALLOCATE at %L", n->sym->name, &n->where);
    8765            2 :           continue;
    8766              :         }
    8767              :       /* Similar for Cray pointer/pointee - they could be implemented but as
    8768              :          common vendor extension but nowadays rarely used and requiring
    8769              :          -fcray-pointer, there is no need to support them.  */
    8770          194 :       if (n->sym->attr.cray_pointer || n->sym->attr.cray_pointee)
    8771              :         {
    8772            2 :           gfc_error ("Sorry, Cray pointers and pointees such as %qs are not "
    8773              :                      "supported with !$OMP ALLOCATE at %L",
    8774              :                      n->sym->name, &n->where);
    8775            2 :           continue;
    8776              :         }
    8777          192 :       n->sym->attr.omp_allocate = 1;
    8778          192 :       if ((n->sym->ts.type == BT_CLASS && n->sym->attr.class_ok
    8779            0 :            && CLASS_DATA (n->sym)->attr.allocatable)
    8780          192 :           || (n->sym->ts.type != BT_CLASS && n->sym->attr.allocatable))
    8781            1 :         gfc_error ("Unexpected allocatable variable %qs at %L in declarative "
    8782              :                    "!$OMP ALLOCATE directive", n->sym->name, &n->where);
    8783          191 :       else if ((n->sym->ts.type == BT_CLASS && n->sym->attr.class_ok
    8784            0 :                 && CLASS_DATA (n->sym)->attr.class_pointer)
    8785          191 :                || (n->sym->ts.type != BT_CLASS && n->sym->attr.pointer))
    8786            1 :         gfc_error ("Unexpected pointer variable %qs at %L in declarative "
    8787              :                    "!$OMP ALLOCATE directive", n->sym->name, &n->where);
    8788          192 :       HOST_WIDE_INT alignment = 0;
    8789          198 :       if (n->u.align
    8790          192 :           && (!gfc_resolve_expr (n->u.align)
    8791           27 :               || n->u.align->ts.type != BT_INTEGER
    8792           26 :               || n->u.align->rank != 0
    8793           24 :               || n->u.align->expr_type != EXPR_CONSTANT
    8794           23 :               || gfc_extract_hwi (n->u.align, &alignment)
    8795           23 :               || !pow2p_hwi (alignment)))
    8796              :         {
    8797            6 :           gfc_error ("ALIGN requires a scalar positive constant integer "
    8798              :                      "alignment expression at %L that is a power of two",
    8799            6 :                      &n->u.align->where);
    8800            6 :           while (n->sym->attr.in_common && n->next && n->next->sym
    8801            6 :                  && n->sym->common_head == n->next->sym->common_head)
    8802              :             n = n->next;
    8803            6 :           continue;
    8804              :         }
    8805          186 :       if (n->sym->attr.in_common || n->sym->attr.save || n->sym->ns->save_all
    8806           63 :           || (n->sym->ns->proc_name
    8807           63 :               && (n->sym->ns->proc_name->attr.flavor == FL_PROGRAM
    8808              :                   || n->sym->ns->proc_name->attr.flavor == FL_MODULE
    8809              :                   || n->sym->ns->proc_name->attr.flavor == FL_BLOCK_DATA)))
    8810              :         {
    8811          131 :           bool com = n->sym->attr.in_common;
    8812          131 :           if (!n->u2.allocator)
    8813            1 :             gfc_error ("An ALLOCATOR clause is required as the list item "
    8814              :                        "%<%s%s%s%> at %L has the SAVE attribute", com ? "/" : "",
    8815            0 :                        com ? n->sym->common_head->name : n->sym->name,
    8816              :                        com ? "/" : "", &n->where);
    8817          130 :           else if (!is_predefined_allocator (n->u2.allocator))
    8818           24 :             gfc_error ("Predefined allocator required in ALLOCATOR clause at %L"
    8819              :                        " as the list item %<%s%s%s%> at %L has the SAVE attribute",
    8820           24 :                        &n->u2.allocator->where, com ? "/" : "",
    8821           24 :                        com ? n->sym->common_head->name : n->sym->name,
    8822              :                        com ? "/" : "", &n->where);
    8823              :           /* Only local static variables might use omp_cgroup_mem_alloc (6),
    8824              :              omp_pteam_mem_alloc (7), or omp_thread_mem_alloc (8).  */
    8825          106 :           else if ((!ns->proc_name
    8826           98 :                     || ns->proc_name->attr.flavor == FL_PROGRAM
    8827              :                     || ns->proc_name->attr.flavor == FL_BLOCK_DATA
    8828              :                     || ns->proc_name->attr.flavor == FL_MODULE
    8829           54 :                     || com)
    8830           74 :                    && mpz_cmp_si (n->u2.allocator->value.integer,
    8831              :                                   6 /* cgroup */) >= 0
    8832           24 :                    && mpz_cmp_si (n->u2.allocator->value.integer,
    8833              :                                   8 /* thread */) <= 0)
    8834              :             {
    8835           24 :               const char *alloc_name[] = {"omp_cgroup_mem_alloc",
    8836              :                                           "omp_pteam_mem_alloc",
    8837              :                                           "omp_thread_mem_alloc" };
    8838           24 :               gfc_error ("Predefined allocator %qs in ALLOCATOR clause at %L, "
    8839              :                          "used for list item %<%s%s%s%> at %L, may only be used"
    8840              :                          " for local static variables",
    8841           24 :                          alloc_name[mpz_get_ui (n->u2.allocator->value.integer)
    8842           24 :                                     - 6 /* cgroup */], &n->u2.allocator->where,
    8843              :                          com ? "/" : "",
    8844           24 :                          com ? n->sym->common_head->name : n->sym->name,
    8845              :                          com ? "/" : "", &n->where);
    8846              :             }
    8847           67 :           while (n->sym->attr.in_common && n->next && n->next->sym
    8848          186 :                  && n->sym->common_head == n->next->sym->common_head)
    8849              :             n = n->next;
    8850              :         }
    8851           55 :       else if (n->u2.allocator
    8852           55 :           && (!gfc_resolve_expr (n->u2.allocator)
    8853           20 :               || n->u2.allocator->ts.type != BT_INTEGER
    8854           19 :               || n->u2.allocator->rank != 0
    8855           18 :               || n->u2.allocator->ts.kind != gfc_c_intptr_kind))
    8856            3 :         gfc_error ("Expected integer expression of the "
    8857              :                    "%<omp_allocator_handle_kind%> kind at %L",
    8858            3 :                    &n->u2.allocator->where);
    8859              :     }
    8860           62 : }
    8861              : 
    8862              : /* Resolve ASSUME's and ASSUMES' assumption clauses.  Note that absent/contains
    8863              :    is handled during parse time in omp_verify_merge_absent_contains.   */
    8864              : 
    8865              : void
    8866           29 : gfc_resolve_omp_assumptions (gfc_omp_assumptions *assume)
    8867              : {
    8868           46 :   for (gfc_expr_list *el = assume->holds; el; el = el->next)
    8869           17 :     if (!gfc_resolve_expr (el->expr)
    8870           17 :         || el->expr->ts.type != BT_LOGICAL
    8871           32 :         || el->expr->rank != 0)
    8872            4 :       gfc_error ("HOLDS expression at %L must be a scalar logical expression",
    8873            4 :                  &el->expr->where);
    8874           29 : }
    8875              : 
    8876              : 
    8877              : /* OpenMP directive resolving routines.  */
    8878              : 
    8879              : static void
    8880        32157 : resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
    8881              :                      gfc_namespace *ns, bool openacc = false)
    8882              : {
    8883        32157 :   gfc_omp_namelist *n, *last;
    8884        32157 :   gfc_expr_list *el;
    8885        32157 :   int list;
    8886        32157 :   int ifc;
    8887        32157 :   bool if_without_mod = false;
    8888        32157 :   gfc_omp_linear_op linear_op = OMP_LINEAR_DEFAULT;
    8889        32157 :   static const char *clause_names[]
    8890              :     = { "PRIVATE", "FIRSTPRIVATE", "LASTPRIVATE", "COPYPRIVATE", "SHARED",
    8891              :         "COPYIN", "UNIFORM", "AFFINITY", "ALIGNED", "LINEAR", "DEPEND", "MAP",
    8892              :         "TO", "FROM", "INCLUSIVE", "EXCLUSIVE",
    8893              :         "REDUCTION", "REDUCTION" /*inscan*/, "REDUCTION" /*task*/,
    8894              :         "IN_REDUCTION", "TASK_REDUCTION",
    8895              :         "DEVICE_RESIDENT", "LINK", "LOCAL", "USE_DEVICE",
    8896              :         "CACHE", "IS_DEVICE_PTR", "USE_DEVICE_PTR", "USE_DEVICE_ADDR",
    8897              :         "NONTEMPORAL", "ALLOCATE", "HAS_DEVICE_ADDR", "ENTER",
    8898              :         "USES_ALLOCATORS", "INIT", "USE", "DESTROY", "INTEROP", "ADJUST_ARGS" };
    8899        32157 :   STATIC_ASSERT (ARRAY_SIZE (clause_names) == OMP_LIST_NUM);
    8900              : 
    8901        32157 :   if (omp_clauses == NULL)
    8902              :     return;
    8903              : 
    8904        32157 :   if (ns == NULL)
    8905        31736 :     ns = gfc_current_ns;
    8906              : 
    8907        32157 :   if (omp_clauses->orderedc && omp_clauses->orderedc < omp_clauses->collapse)
    8908            0 :     gfc_error ("ORDERED clause parameter is less than COLLAPSE at %L",
    8909              :                &code->loc);
    8910        32157 :   if (omp_clauses->order_concurrent && omp_clauses->ordered)
    8911            4 :     gfc_error ("ORDER clause must not be used together with ORDERED at %L",
    8912              :                &code->loc);
    8913        32157 :   if (omp_clauses->if_expr)
    8914              :     {
    8915         1184 :       gfc_expr *expr = omp_clauses->if_expr;
    8916         1184 :       if (!gfc_resolve_expr (expr)
    8917         1184 :           || expr->ts.type != BT_LOGICAL || expr->rank != 0)
    8918           16 :         gfc_error ("IF clause at %L requires a scalar LOGICAL expression",
    8919              :                    &expr->where);
    8920              :       if_without_mod = true;
    8921              :     }
    8922       353727 :   for (ifc = 0; ifc < OMP_IF_LAST; ifc++)
    8923       321570 :     if (omp_clauses->if_exprs[ifc])
    8924              :       {
    8925          137 :         gfc_expr *expr = omp_clauses->if_exprs[ifc];
    8926          137 :         bool ok = true;
    8927          137 :         if (!gfc_resolve_expr (expr)
    8928          137 :             || expr->ts.type != BT_LOGICAL || expr->rank != 0)
    8929            0 :           gfc_error ("IF clause at %L requires a scalar LOGICAL expression",
    8930              :                      &expr->where);
    8931          137 :         else if (if_without_mod)
    8932              :           {
    8933            1 :             gfc_error ("IF clause without modifier at %L used together with "
    8934              :                        "IF clauses with modifiers",
    8935            1 :                        &omp_clauses->if_expr->where);
    8936            1 :             if_without_mod = false;
    8937              :           }
    8938              :         else
    8939          136 :           switch (code->op)
    8940              :             {
    8941           13 :             case EXEC_OMP_CANCEL:
    8942           13 :               ok = ifc == OMP_IF_CANCEL;
    8943           13 :               break;
    8944              : 
    8945           16 :             case EXEC_OMP_PARALLEL:
    8946           16 :             case EXEC_OMP_PARALLEL_DO:
    8947           16 :             case EXEC_OMP_PARALLEL_LOOP:
    8948           16 :             case EXEC_OMP_PARALLEL_MASKED:
    8949           16 :             case EXEC_OMP_PARALLEL_MASTER:
    8950           16 :             case EXEC_OMP_PARALLEL_SECTIONS:
    8951           16 :             case EXEC_OMP_PARALLEL_WORKSHARE:
    8952           16 :             case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
    8953           16 :             case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
    8954           16 :               ok = ifc == OMP_IF_PARALLEL;
    8955           16 :               break;
    8956              : 
    8957           28 :             case EXEC_OMP_PARALLEL_DO_SIMD:
    8958           28 :             case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
    8959           28 :             case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
    8960           28 :               ok = ifc == OMP_IF_PARALLEL || ifc == OMP_IF_SIMD;
    8961           28 :               break;
    8962              : 
    8963            8 :             case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
    8964            8 :             case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
    8965            8 :               ok = ifc == OMP_IF_PARALLEL || ifc == OMP_IF_TASKLOOP;
    8966            8 :               break;
    8967              : 
    8968           12 :             case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
    8969           12 :             case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
    8970           12 :               ok = (ifc == OMP_IF_PARALLEL
    8971           12 :                     || ifc == OMP_IF_TASKLOOP
    8972              :                     || ifc == OMP_IF_SIMD);
    8973              :               break;
    8974              : 
    8975            0 :             case EXEC_OMP_SIMD:
    8976            0 :             case EXEC_OMP_DO_SIMD:
    8977            0 :             case EXEC_OMP_DISTRIBUTE_SIMD:
    8978            0 :             case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
    8979            0 :               ok = ifc == OMP_IF_SIMD;
    8980            0 :               break;
    8981              : 
    8982            1 :             case EXEC_OMP_TASK:
    8983            1 :               ok = ifc == OMP_IF_TASK;
    8984            1 :               break;
    8985              : 
    8986            5 :             case EXEC_OMP_TASKLOOP:
    8987            5 :             case EXEC_OMP_MASKED_TASKLOOP:
    8988            5 :             case EXEC_OMP_MASTER_TASKLOOP:
    8989            5 :               ok = ifc == OMP_IF_TASKLOOP;
    8990            5 :               break;
    8991              : 
    8992           20 :             case EXEC_OMP_TASKLOOP_SIMD:
    8993           20 :             case EXEC_OMP_MASKED_TASKLOOP_SIMD:
    8994           20 :             case EXEC_OMP_MASTER_TASKLOOP_SIMD:
    8995           20 :               ok = ifc == OMP_IF_TASKLOOP || ifc == OMP_IF_SIMD;
    8996           20 :               break;
    8997              : 
    8998            5 :             case EXEC_OMP_TARGET:
    8999            5 :             case EXEC_OMP_TARGET_TEAMS:
    9000            5 :             case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
    9001            5 :             case EXEC_OMP_TARGET_TEAMS_LOOP:
    9002            5 :               ok = ifc == OMP_IF_TARGET;
    9003            5 :               break;
    9004              : 
    9005            4 :             case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
    9006            4 :             case EXEC_OMP_TARGET_SIMD:
    9007            4 :               ok = ifc == OMP_IF_TARGET || ifc == OMP_IF_SIMD;
    9008            4 :               break;
    9009              : 
    9010            1 :             case EXEC_OMP_TARGET_DATA:
    9011            1 :               ok = ifc == OMP_IF_TARGET_DATA;
    9012            1 :               break;
    9013              : 
    9014            1 :             case EXEC_OMP_TARGET_UPDATE:
    9015            1 :               ok = ifc == OMP_IF_TARGET_UPDATE;
    9016            1 :               break;
    9017              : 
    9018            1 :             case EXEC_OMP_TARGET_ENTER_DATA:
    9019            1 :               ok = ifc == OMP_IF_TARGET_ENTER_DATA;
    9020            1 :               break;
    9021              : 
    9022            1 :             case EXEC_OMP_TARGET_EXIT_DATA:
    9023            1 :               ok = ifc == OMP_IF_TARGET_EXIT_DATA;
    9024            1 :               break;
    9025              : 
    9026           10 :             case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
    9027           10 :             case EXEC_OMP_TARGET_PARALLEL:
    9028           10 :             case EXEC_OMP_TARGET_PARALLEL_DO:
    9029           10 :             case EXEC_OMP_TARGET_PARALLEL_LOOP:
    9030           10 :               ok = ifc == OMP_IF_TARGET || ifc == OMP_IF_PARALLEL;
    9031           10 :               break;
    9032              : 
    9033           10 :             case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
    9034           10 :             case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
    9035           10 :               ok = (ifc == OMP_IF_TARGET
    9036           10 :                     || ifc == OMP_IF_PARALLEL
    9037              :                     || ifc == OMP_IF_SIMD);
    9038              :               break;
    9039              : 
    9040              :             default:
    9041              :               ok = false;
    9042              :               break;
    9043              :           }
    9044          115 :         if (!ok)
    9045              :           {
    9046            2 :             static const char *ifs[] = {
    9047              :               "CANCEL",
    9048              :               "PARALLEL",
    9049              :               "SIMD",
    9050              :               "TASK",
    9051              :               "TASKLOOP",
    9052              :               "TARGET",
    9053              :               "TARGET DATA",
    9054              :               "TARGET UPDATE",
    9055              :               "TARGET ENTER DATA",
    9056              :               "TARGET EXIT DATA"
    9057              :             };
    9058            2 :             gfc_error ("IF clause modifier %s at %L not appropriate for "
    9059              :                        "the current OpenMP construct", ifs[ifc], &expr->where);
    9060              :           }
    9061              :       }
    9062              : 
    9063        32157 :   if (omp_clauses->self_expr)
    9064              :     {
    9065          177 :       gfc_expr *expr = omp_clauses->self_expr;
    9066          177 :       if (!gfc_resolve_expr (expr)
    9067          177 :           || expr->ts.type != BT_LOGICAL || expr->rank != 0)
    9068            6 :         gfc_error ("SELF clause at %L requires a scalar LOGICAL expression",
    9069              :                    &expr->where);
    9070              :     }
    9071              : 
    9072        32157 :   if (omp_clauses->final_expr)
    9073              :     {
    9074           64 :       gfc_expr *expr = omp_clauses->final_expr;
    9075           64 :       if (!gfc_resolve_expr (expr)
    9076           64 :           || expr->ts.type != BT_LOGICAL || expr->rank != 0)
    9077            0 :         gfc_error ("FINAL clause at %L requires a scalar LOGICAL expression",
    9078              :                    &expr->where);
    9079              :     }
    9080        32157 :   if (omp_clauses->novariants)
    9081              :     {
    9082            9 :       gfc_expr *expr = omp_clauses->novariants;
    9083           18 :       if (!gfc_resolve_expr (expr) || expr->ts.type != BT_LOGICAL
    9084           17 :           || expr->rank != 0)
    9085            1 :         gfc_error (
    9086              :           "NOVARIANTS clause at %L requires a scalar LOGICAL expression",
    9087              :           &expr->where);
    9088        32157 :       if_without_mod = true;
    9089              :     }
    9090        32157 :   if (omp_clauses->nocontext)
    9091              :     {
    9092           12 :       gfc_expr *expr = omp_clauses->nocontext;
    9093           24 :       if (!gfc_resolve_expr (expr) || expr->ts.type != BT_LOGICAL
    9094           23 :           || expr->rank != 0)
    9095            1 :         gfc_error (
    9096              :           "NOCONTEXT clause at %L requires a scalar LOGICAL expression",
    9097              :           &expr->where);
    9098        32157 :       if_without_mod = true;
    9099              :     }
    9100        32157 :   if (omp_clauses->num_threads)
    9101          950 :     resolve_positive_int_expr (omp_clauses->num_threads, "NUM_THREADS");
    9102        32157 :   if (omp_clauses->dyn_groupprivate)
    9103           10 :     resolve_nonnegative_int_expr (omp_clauses->dyn_groupprivate,
    9104              :                                   "DYN_GROUPPRIVATE");
    9105        32157 :   if (omp_clauses->chunk_size)
    9106              :     {
    9107          510 :       gfc_expr *expr = omp_clauses->chunk_size;
    9108          510 :       if (!gfc_resolve_expr (expr)
    9109          510 :           || expr->ts.type != BT_INTEGER || expr->rank != 0)
    9110            0 :         gfc_error ("SCHEDULE clause's chunk_size at %L requires "
    9111              :                    "a scalar INTEGER expression", &expr->where);
    9112          510 :       else if (expr->expr_type == EXPR_CONSTANT
    9113              :                && expr->ts.type == BT_INTEGER
    9114          485 :                && mpz_sgn (expr->value.integer) <= 0)
    9115            2 :         gfc_warning (OPT_Wopenmp, "INTEGER expression of SCHEDULE clause's "
    9116              :                      "chunk_size at %L must be positive", &expr->where);
    9117              :     }
    9118        32157 :   if (omp_clauses->sched_kind != OMP_SCHED_NONE
    9119          891 :       && omp_clauses->sched_nonmonotonic)
    9120              :     {
    9121           34 :       if (omp_clauses->sched_monotonic)
    9122            2 :         gfc_error ("Both MONOTONIC and NONMONOTONIC schedule modifiers "
    9123              :                    "specified at %L", &code->loc);
    9124           32 :       else if (omp_clauses->ordered)
    9125            4 :         gfc_error ("NONMONOTONIC schedule modifier specified with ORDERED "
    9126              :                    "clause at %L", &code->loc);
    9127              :     }
    9128              : 
    9129        32157 :   if (omp_clauses->depobj
    9130        32157 :       && (!gfc_resolve_expr (omp_clauses->depobj)
    9131          115 :           || omp_clauses->depobj->ts.type != BT_INTEGER
    9132          114 :           || omp_clauses->depobj->ts.kind != 2 * gfc_index_integer_kind
    9133          113 :           || omp_clauses->depobj->rank != 0))
    9134            4 :     gfc_error ("DEPOBJ in DEPOBJ construct at %L shall be a scalar integer "
    9135            4 :                "of OMP_DEPEND_KIND kind", &omp_clauses->depobj->where);
    9136              : 
    9137              :   /* Check that no symbol appears on multiple clauses, except that
    9138              :      a symbol can appear on both firstprivate and lastprivate.  */
    9139      1286280 :   for (list = 0; list < OMP_LIST_NUM; list++)
    9140      1299004 :     for (n = omp_clauses->lists[list]; n; n = n->next)
    9141              :       {
    9142        44881 :         if (!n->sym)  /* omp_all_memory.  */
    9143           47 :           continue;
    9144        44834 :         n->sym->mark = 0;
    9145        44834 :         n->sym->comp_mark = 0;
    9146        44834 :         n->sym->data_mark = 0;
    9147        44834 :         n->sym->dev_mark = 0;
    9148        44834 :         n->sym->gen_mark = 0;
    9149        44834 :         n->sym->reduc_mark = 0;
    9150        44834 :         if (n->sym->attr.flavor == FL_VARIABLE
    9151          274 :             || n->sym->attr.proc_pointer
    9152          233 :             || (!code && (!n->sym->attr.dummy || n->sym->ns != ns)))
    9153              :           {
    9154        44601 :             if (!code && (!n->sym->attr.dummy || n->sym->ns != ns))
    9155            0 :               gfc_error ("Variable %qs is not a dummy argument at %L",
    9156              :                          n->sym->name, &n->where);
    9157        44601 :             continue;
    9158              :           }
    9159          233 :         if (n->sym->attr.flavor == FL_PROCEDURE
    9160          153 :             && n->sym->result == n->sym
    9161          138 :             && n->sym->attr.function)
    9162              :           {
    9163          138 :             if (ns->proc_name == n->sym
    9164           44 :                 || (ns->parent && ns->parent->proc_name == n->sym))
    9165          101 :               continue;
    9166           37 :             if (ns->proc_name->attr.entry_master)
    9167              :               {
    9168           32 :                 gfc_entry_list *el = ns->entries;
    9169           51 :                 for (; el; el = el->next)
    9170           51 :                   if (el->sym == n->sym)
    9171              :                     break;
    9172           32 :                 if (el)
    9173           32 :                   continue;
    9174              :               }
    9175            5 :             if (ns->parent
    9176            3 :                 && ns->parent->proc_name->attr.entry_master)
    9177              :               {
    9178            2 :                 gfc_entry_list *el = ns->parent->entries;
    9179            3 :                 for (; el; el = el->next)
    9180            3 :                   if (el->sym == n->sym)
    9181              :                     break;
    9182            2 :                 if (el)
    9183            2 :                   continue;
    9184              :               }
    9185              :           }
    9186           98 :         if (list == OMP_LIST_MAP
    9187           18 :             && n->sym->attr.flavor == FL_PARAMETER)
    9188              :           {
    9189              :             /* OpenACC since 3.4 permits for Fortran named constants, but
    9190              :                permits removing then as optimization is not needed and such
    9191              :                ignore them. Likewise below for FIRSTPRIVATE.  */
    9192           12 :             if (openacc)
    9193           10 :               gfc_warning (OPT_Wsurprising, "Clause for object %qs at %L is "
    9194              :                            "ignored as parameters need not be copied",
    9195              :                            n->sym->name, &n->where);
    9196              :             else
    9197            2 :               gfc_error ("Object %qs is not a variable at %L; parameters"
    9198              :                          " cannot be and need not be mapped", n->sym->name,
    9199              :                          &n->where);
    9200              :           }
    9201           86 :         else if (openacc && n->sym->attr.flavor == FL_PARAMETER)
    9202            9 :           gfc_warning (OPT_Wsurprising, "Clause for object %qs at %L is ignored"
    9203              :                        " as it is a parameter", n->sym->name, &n->where);
    9204           77 :         else if (list != OMP_LIST_USES_ALLOCATORS)
    9205           30 :           gfc_error ("Object %qs is not a variable at %L", n->sym->name,
    9206              :                      &n->where);
    9207              :       }
    9208        32157 :   if (omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN])
    9209              :     {
    9210           69 :       locus *loc = &omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN]->where;
    9211           69 :       if (code->op != EXEC_OMP_DO
    9212              :           && code->op != EXEC_OMP_SIMD
    9213              :           && code->op != EXEC_OMP_DO_SIMD
    9214              :           && code->op != EXEC_OMP_PARALLEL_DO
    9215              :           && code->op != EXEC_OMP_PARALLEL_DO_SIMD)
    9216           23 :         gfc_error ("%<inscan%> REDUCTION clause on construct other than DO, "
    9217              :                    "SIMD, DO SIMD, PARALLEL DO, PARALLEL DO SIMD at %L",
    9218              :                    loc);
    9219           69 :       if (omp_clauses->ordered)
    9220            2 :         gfc_error ("ORDERED clause specified together with %<inscan%> "
    9221              :                    "REDUCTION clause at %L", loc);
    9222           69 :       if (omp_clauses->sched_kind != OMP_SCHED_NONE)
    9223            3 :         gfc_error ("SCHEDULE clause specified together with %<inscan%> "
    9224              :                    "REDUCTION clause at %L", loc);
    9225              :     }
    9226              : 
    9227      1286280 :   for (list = 0; list < OMP_LIST_NUM; list++)
    9228      1254123 :     if (list != OMP_LIST_FIRSTPRIVATE
    9229      1254123 :         && list != OMP_LIST_LASTPRIVATE
    9230      1254123 :         && list != OMP_LIST_ALIGNED
    9231      1157652 :         && list != OMP_LIST_DEPEND
    9232      1157652 :         && list != OMP_LIST_FROM
    9233      1093338 :         && list != OMP_LIST_TO
    9234      1093338 :         && list != OMP_LIST_INTEROP
    9235      1029024 :         && (list != OMP_LIST_REDUCTION || !openacc)
    9236      1016407 :         && list != OMP_LIST_ALLOCATE)
    9237      1018351 :       for (n = omp_clauses->lists[list]; n; n = n->next)
    9238              :         {
    9239        34101 :           bool component_ref_p = false;
    9240              : 
    9241              :           /* Allow multiple components of the same (e.g. derived-type)
    9242              :              variable here.  Duplicate components are detected elsewhere.  */
    9243        34101 :           if (n->expr && n->expr->expr_type == EXPR_VARIABLE)
    9244        15378 :             for (gfc_ref *ref = n->expr->ref; ref; ref = ref->next)
    9245         9379 :               if (ref->type == REF_COMPONENT)
    9246         3134 :                 component_ref_p = true;
    9247        34101 :           if ((list == OMP_LIST_IS_DEVICE_PTR
    9248        34101 :                || list == OMP_LIST_HAS_DEVICE_ADDR)
    9249          313 :               && !component_ref_p)
    9250              :             {
    9251          313 :               if (n->sym->gen_mark
    9252          311 :                   || n->sym->dev_mark
    9253          310 :                   || n->sym->reduc_mark
    9254          310 :                   || n->sym->mark)
    9255            5 :                 gfc_error ("Symbol %qs present on multiple clauses at %L",
    9256              :                            n->sym->name, &n->where);
    9257              :               else
    9258          308 :                 n->sym->dev_mark = 1;
    9259              :             }
    9260        33788 :           else if ((list == OMP_LIST_USE_DEVICE_PTR
    9261        33788 :                     || list == OMP_LIST_USE_DEVICE_ADDR
    9262        33788 :                     || list == OMP_LIST_PRIVATE
    9263              :                     || list == OMP_LIST_SHARED)
    9264        12817 :                    && !component_ref_p)
    9265              :             {
    9266        12817 :               if (n->sym->gen_mark || n->sym->dev_mark || n->sym->reduc_mark)
    9267           13 :                 gfc_error ("Symbol %qs present on multiple clauses at %L",
    9268              :                            n->sym->name, &n->where);
    9269              :               else
    9270              :                 {
    9271        12804 :                   n->sym->gen_mark = 1;
    9272              :                   /* Set both generic and device bits if we have
    9273              :                      use_device_*(x) or shared(x).  This allows us to diagnose
    9274              :                      "map(x) private(x)" below.  */
    9275        12804 :                   if (list != OMP_LIST_PRIVATE)
    9276         3438 :                     n->sym->dev_mark = 1;
    9277              :                 }
    9278              :             }
    9279        20971 :           else if ((list == OMP_LIST_REDUCTION
    9280        20971 :                     || list == OMP_LIST_REDUCTION_TASK
    9281        18515 :                     || list == OMP_LIST_REDUCTION_INSCAN
    9282        18515 :                     || list == OMP_LIST_IN_REDUCTION
    9283        18302 :                     || list == OMP_LIST_TASK_REDUCTION)
    9284         2669 :                    && !component_ref_p)
    9285              :             {
    9286              :               /* Attempts to mix reduction types are diagnosed below.  */
    9287         2669 :               if (n->sym->gen_mark || n->sym->dev_mark)
    9288            2 :                 gfc_error ("Symbol %qs present on multiple clauses at %L",
    9289              :                            n->sym->name, &n->where);
    9290         2669 :               n->sym->reduc_mark = 1;
    9291              :             }
    9292        18302 :           else if ((!component_ref_p && n->sym->comp_mark)
    9293         2451 :                    || (component_ref_p && n->sym->mark))
    9294              :             {
    9295           28 :               if (openacc)
    9296            3 :                 gfc_error ("Symbol %qs has mixed component and non-component "
    9297            3 :                            "accesses at %L", n->sym->name, &n->where);
    9298              :             }
    9299        18274 :           else if (n->sym->mark)
    9300           89 :             gfc_error ("Symbol %qs present on multiple clauses at %L",
    9301              :                        n->sym->name, &n->where);
    9302              :           else
    9303              :             {
    9304        18185 :               if (component_ref_p)
    9305         2424 :                 n->sym->comp_mark = 1;
    9306              :               else
    9307        15761 :                 n->sym->mark = 1;
    9308              :             }
    9309              :         }
    9310              : 
    9311        32157 :   if (code
    9312        31939 :       && code->op == EXEC_OMP_INTEROP
    9313           63 :       && omp_clauses->lists[OMP_LIST_DEPEND])
    9314              :     {
    9315           12 :       if (!omp_clauses->lists[OMP_LIST_INIT]
    9316            5 :           && !omp_clauses->lists[OMP_LIST_USE]
    9317            1 :           && !omp_clauses->lists[OMP_LIST_DESTROY])
    9318              :         {
    9319            1 :           gfc_error ("DEPEND clause at %L requires action clause with "
    9320              :                      "%<targetsync%> interop-type",
    9321              :                      &omp_clauses->lists[OMP_LIST_DEPEND]->where);
    9322              :         }
    9323           22 :       for (n = omp_clauses->lists[OMP_LIST_INIT]; n; n = n->next)
    9324           12 :         if (!n->u.init.targetsync)
    9325              :           {
    9326            2 :             gfc_error ("DEPEND clause at %L requires %<targetsync%> "
    9327              :                        "interop-type, lacking it for %qs at %L",
    9328            2 :                        &omp_clauses->lists[OMP_LIST_DEPEND]->where,
    9329            2 :                        n->sym->name, &n->where);
    9330            2 :             break;
    9331              :           }
    9332              :     }
    9333        31939 :   if (code && (code->op == EXEC_OMP_INTEROP || code->op == EXEC_OMP_DISPATCH))
    9334         1085 :     for (list = OMP_LIST_INIT; list <= OMP_LIST_INTEROP; list++)
    9335         1123 :       for (n = omp_clauses->lists[list]; n; n = n->next)
    9336              :         {
    9337          255 :           if (n->sym->ts.type != BT_INTEGER
    9338          252 :               || n->sym->ts.kind != gfc_index_integer_kind
    9339          248 :               || n->sym->attr.dimension
    9340          243 :               || n->sym->attr.flavor != FL_VARIABLE)
    9341           16 :             gfc_error ("%qs at %L in %qs clause must be a scalar integer "
    9342              :                        "variable of %<omp_interop_kind%> kind", n->sym->name,
    9343              :                        &n->where, clause_names[list]);
    9344          255 :           if (list != OMP_LIST_USE && list != OMP_LIST_INTEROP
    9345          109 :               && n->sym->attr.intent == INTENT_IN)
    9346            2 :             gfc_error ("%qs at %L in %qs clause must be definable",
    9347              :                        n->sym->name, &n->where, clause_names[list]);
    9348              :         }
    9349              : 
    9350              :   /* Detect specifically the case where we have "map(x) private(x)" and raise
    9351              :      an error.  If we have "...simd" combined directives though, the "private"
    9352              :      applies to the simd part, so this is permitted though.  */
    9353        41531 :   for (n = omp_clauses->lists[OMP_LIST_PRIVATE]; n; n = n->next)
    9354         9374 :     if (n->sym->mark
    9355            6 :         && n->sym->gen_mark
    9356            6 :         && !n->sym->dev_mark
    9357            6 :         && !n->sym->reduc_mark
    9358            5 :         && code->op != EXEC_OMP_TARGET_SIMD
    9359              :         && code->op != EXEC_OMP_TARGET_PARALLEL_DO_SIMD
    9360              :         && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD
    9361              :         && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD)
    9362            1 :       gfc_error ("Symbol %qs present on multiple clauses at %L",
    9363              :                  n->sym->name, &n->where);
    9364              : 
    9365              :   gcc_assert (OMP_LIST_LASTPRIVATE == OMP_LIST_FIRSTPRIVATE + 1);
    9366        96471 :   for (list = OMP_LIST_FIRSTPRIVATE; list <= OMP_LIST_LASTPRIVATE; list++)
    9367        68432 :     for (n = omp_clauses->lists[list]; n; n = n->next)
    9368         4118 :       if (n->sym->data_mark || n->sym->gen_mark || n->sym->dev_mark)
    9369              :         {
    9370            9 :           gfc_error ("Symbol %qs present on multiple clauses at %L",
    9371              :                      n->sym->name, &n->where);
    9372            9 :           n->sym->data_mark = n->sym->gen_mark = n->sym->dev_mark = 0;
    9373              :         }
    9374         4109 :       else if (n->sym->mark
    9375           17 :                && code->op != EXEC_OMP_TARGET_TEAMS
    9376              :                && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE
    9377              :                && code->op != EXEC_OMP_TARGET_TEAMS_LOOP
    9378              :                && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD
    9379              :                && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO
    9380              :                && code->op != EXEC_OMP_TARGET_PARALLEL
    9381              :                && code->op != EXEC_OMP_TARGET_PARALLEL_DO
    9382              :                && code->op != EXEC_OMP_TARGET_PARALLEL_LOOP
    9383              :                && code->op != EXEC_OMP_TARGET_PARALLEL_DO_SIMD
    9384              :                && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD)
    9385            6 :         gfc_error ("Symbol %qs present on both data and map clauses "
    9386              :                    "at %L", n->sym->name, &n->where);
    9387              : 
    9388        33969 :   for (n = omp_clauses->lists[OMP_LIST_FIRSTPRIVATE]; n; n = n->next)
    9389              :     {
    9390         1812 :       if (n->sym->data_mark || n->sym->gen_mark || n->sym->dev_mark)
    9391            7 :         gfc_error ("Symbol %qs present on multiple clauses at %L",
    9392              :                    n->sym->name, &n->where);
    9393              :       else
    9394         1805 :         n->sym->data_mark = 1;
    9395              :     }
    9396        34463 :   for (n = omp_clauses->lists[OMP_LIST_LASTPRIVATE]; n; n = n->next)
    9397         2306 :     n->sym->data_mark = 0;
    9398              : 
    9399        34463 :   for (n = omp_clauses->lists[OMP_LIST_LASTPRIVATE]; n; n = n->next)
    9400              :     {
    9401         2306 :       if (n->sym->data_mark || n->sym->gen_mark || n->sym->dev_mark)
    9402            0 :         gfc_error ("Symbol %qs present on multiple clauses at %L",
    9403              :                    n->sym->name, &n->where);
    9404              :       else
    9405         2306 :         n->sym->data_mark = 1;
    9406              :     }
    9407              : 
    9408        32307 :   for (n = omp_clauses->lists[OMP_LIST_ALIGNED]; n; n = n->next)
    9409          150 :     n->sym->mark = 0;
    9410              : 
    9411        32307 :   for (n = omp_clauses->lists[OMP_LIST_ALIGNED]; n; n = n->next)
    9412              :     {
    9413          150 :       if (n->sym->mark)
    9414            0 :         gfc_error ("Symbol %qs present on multiple clauses at %L",
    9415              :                    n->sym->name, &n->where);
    9416              :       else
    9417          150 :         n->sym->mark = 1;
    9418              :     }
    9419              : 
    9420        32157 :   if (omp_clauses->lists[OMP_LIST_ALLOCATE])
    9421              :     {
    9422          791 :       for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; n = n->next)
    9423              :         {
    9424          513 :           if (n->u2.allocator
    9425          513 :               && (!gfc_resolve_expr (n->u2.allocator)
    9426          288 :                   || n->u2.allocator->ts.type != BT_INTEGER
    9427          286 :                   || n->u2.allocator->rank != 0
    9428          285 :                   || n->u2.allocator->ts.kind != gfc_c_intptr_kind))
    9429              :             {
    9430            8 :               gfc_error ("Expected integer expression of the "
    9431              :                          "%<omp_allocator_handle_kind%> kind at %L",
    9432            8 :                          &n->u2.allocator->where);
    9433           28 :               break;
    9434              :             }
    9435          505 :           if (!n->u.align)
    9436          397 :             continue;
    9437          108 :           HOST_WIDE_INT alignment = 0;
    9438          108 :           if (!gfc_resolve_expr (n->u.align)
    9439          108 :               || n->u.align->ts.type != BT_INTEGER
    9440          105 :               || n->u.align->rank != 0
    9441          102 :               || n->u.align->expr_type != EXPR_CONSTANT
    9442           99 :               || gfc_extract_hwi (n->u.align, &alignment)
    9443           99 :               || alignment <= 0
    9444          207 :               || !pow2p_hwi (alignment))
    9445              :             {
    9446           12 :               gfc_error ("ALIGN requires a scalar positive constant integer "
    9447              :                          "alignment expression at %L that is a power of two",
    9448           12 :                          &n->u.align->where);
    9449           12 :               break;
    9450              :             }
    9451              :         }
    9452              : 
    9453              :       /* Check for 2 things here.
    9454              :          1.  There is no duplication of variable in allocate clause.
    9455              :          2.  Variable in allocate clause are also present in some
    9456              :              privatization clase (non-composite case).  */
    9457          811 :       for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; n = n->next)
    9458          513 :         if (n->sym)
    9459          487 :           n->sym->mark = 0;
    9460              : 
    9461              :       gfc_omp_namelist *prev = NULL;
    9462          811 :       for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; )
    9463              :         {
    9464          513 :           if (n->sym == NULL)
    9465              :             {
    9466           26 :               n = n->next;
    9467           26 :               continue;
    9468              :             }
    9469          487 :           if (n->sym->mark == 1)
    9470              :             {
    9471            3 :               gfc_warning (OPT_Wopenmp, "%qs appears more than once in "
    9472              :                            "%<allocate%> at %L" , n->sym->name, &n->where);
    9473              :               /* We have already seen this variable so it is a duplicate.
    9474              :                  Remove it.  */
    9475            3 :               if (prev != NULL && prev->next == n)
    9476              :                 {
    9477            3 :                   prev->next = n->next;
    9478            3 :                   n->next = NULL;
    9479            3 :                   gfc_free_omp_namelist (n, false, true, false, false);
    9480            3 :                   n = prev->next;
    9481              :                 }
    9482            3 :               continue;
    9483              :             }
    9484          484 :           n->sym->mark = 1;
    9485          484 :           prev = n;
    9486          484 :           n = n->next;
    9487              :         }
    9488              : 
    9489              :       /* Non-composite constructs.  */
    9490          298 :       if (code && code->op < EXEC_OMP_DO_SIMD)
    9491              :         {
    9492         4760 :           for (list = 0; list < OMP_LIST_NUM; list++)
    9493         4641 :             switch (list)
    9494              :             {
    9495         1071 :               case OMP_LIST_PRIVATE:
    9496         1071 :               case OMP_LIST_FIRSTPRIVATE:
    9497         1071 :               case OMP_LIST_LASTPRIVATE:
    9498         1071 :               case OMP_LIST_REDUCTION:
    9499         1071 :               case OMP_LIST_REDUCTION_INSCAN:
    9500         1071 :               case OMP_LIST_REDUCTION_TASK:
    9501         1071 :               case OMP_LIST_IN_REDUCTION:
    9502         1071 :               case OMP_LIST_TASK_REDUCTION:
    9503         1071 :               case OMP_LIST_LINEAR:
    9504         1370 :                 for (n = omp_clauses->lists[list]; n; n = n->next)
    9505          299 :                   n->sym->mark = 0;
    9506              :                 break;
    9507              :               default:
    9508              :                 break;
    9509              :             }
    9510              : 
    9511          410 :           for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; n = n->next)
    9512          291 :             if (n->sym->mark == 1)
    9513            4 :               gfc_error ("%qs specified in %<allocate%> clause at %L but not "
    9514              :                          "in an explicit privatization clause",
    9515              :                          n->sym->name, &n->where);
    9516              :         }
    9517              :       if (code
    9518          298 :           && (code->op == EXEC_OMP_ALLOCATORS || code->op == EXEC_OMP_ALLOCATE)
    9519           73 :           && code->block
    9520           72 :           && code->block->next
    9521           71 :           && code->block->next->op == EXEC_ALLOCATE)
    9522              :         {
    9523           68 :           if (code->op == EXEC_OMP_ALLOCATE)
    9524           49 :             gfc_warning (OPT_Wdeprecated_openmp,
    9525              :                          "The use of one or more %<allocate%> directives with "
    9526              :                          "an associated %<allocate%> statement at %L is "
    9527              :                          "deprecated since OpenMP 5.2, use an %<allocators%> "
    9528              :                          "directive", &code->loc);
    9529           68 :           gfc_alloc *a;
    9530           68 :           gfc_omp_namelist *n_null = NULL;
    9531           68 :           bool missing_allocator = false;
    9532           68 :           gfc_symbol *missing_allocator_sym = NULL;
    9533          161 :           for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; n = n->next)
    9534              :             {
    9535           93 :               if (n->u2.allocator == NULL)
    9536              :                 {
    9537           77 :                   if (!missing_allocator_sym)
    9538           59 :                     missing_allocator_sym = n->sym;
    9539              :                   missing_allocator = true;
    9540              :                 }
    9541           93 :               if (n->sym == NULL)
    9542              :                 {
    9543           26 :                   n_null = n;
    9544           26 :                   continue;
    9545              :                 }
    9546           67 :               if (n->sym->attr.codimension)
    9547            2 :                 gfc_error ("Unexpected coarray %qs in %<allocate%> at %L",
    9548              :                            n->sym->name, &n->where);
    9549          103 :               for (a = code->block->next->ext.alloc.list; a; a = a->next)
    9550          101 :                 if (a->expr->expr_type == EXPR_VARIABLE
    9551          101 :                   && a->expr->symtree->n.sym == n->sym)
    9552              :                   {
    9553           65 :                     gfc_ref *ref;
    9554           82 :                     for (ref = a->expr->ref; ref; ref = ref->next)
    9555           17 :                       if (ref->type == REF_COMPONENT)
    9556              :                         break;
    9557              :                     if (ref == NULL)
    9558              :                       break;
    9559              :                   }
    9560           67 :               if (a == NULL)
    9561            2 :                 gfc_error ("%qs specified in %<allocate%> at %L but not "
    9562              :                            "in the associated ALLOCATE statement",
    9563            2 :                            n->sym->name, &n->where);
    9564              :             }
    9565              :           /* If there is an ALLOCATE directive without list argument, a
    9566              :              namelist with its allocator/align clauses and n->sym = NULL is
    9567              :              created during parsing; here, we add all not otherwise specified
    9568              :              items from the Fortran allocate to that list.
    9569              :              For an ALLOCATORS directive, not listed items use the normal
    9570              :              Fortran way.
    9571              :              The behavior of an ALLOCATE directive that does not list all
    9572              :              arguments but there is no directive without list argument is not
    9573              :              well specified.  Thus, we reject such code below. In OpenMP 5.2
    9574              :              the executable ALLOCATE directive is deprecated and in 6.0
    9575              :              deleted such that no spec clarification is to be expected.  */
    9576          125 :           for (a = code->block->next->ext.alloc.list; a; a = a->next)
    9577           89 :             if (a->expr->expr_type == EXPR_VARIABLE)
    9578              :               {
    9579          154 :                 for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; n = n->next)
    9580          122 :                   if (a->expr->symtree->n.sym == n->sym)
    9581              :                     {
    9582           57 :                       gfc_ref *ref;
    9583           72 :                       for (ref = a->expr->ref; ref; ref = ref->next)
    9584           15 :                         if (ref->type == REF_COMPONENT)
    9585              :                           break;
    9586              :                       if (ref == NULL)
    9587              :                         break;
    9588              :                     }
    9589           89 :                 if (n == NULL && n_null == NULL)
    9590              :                   {
    9591              :                     /* OK for ALLOCATORS but for ALLOCATE: Unspecified whether
    9592              :                        that should use the default allocator of OpenMP or the
    9593              :                        Fortran allocator. Thus, just reject it.  */
    9594            7 :                     if (code->op == EXEC_OMP_ALLOCATE)
    9595            1 :                       gfc_error ("%qs listed in %<allocate%> statement at %L "
    9596              :                                  "but it is neither explicitly in listed in "
    9597              :                                  "the %<!$OMP ALLOCATE%> directive nor exists"
    9598              :                                  " a directive without argument list",
    9599            1 :                                  a->expr->symtree->n.sym->name,
    9600              :                                  &a->expr->where);
    9601              :                     break;
    9602              :                   }
    9603           82 :                 if (n == NULL)
    9604              :                   {
    9605           25 :                     if (a->expr->symtree->n.sym->attr.codimension)
    9606            1 :                       gfc_error ("Unexpected coarray %qs in %<allocate%> at "
    9607              :                                  "%L, implicitly listed in %<!$OMP ALLOCATE%>"
    9608              :                                  " at %L", a->expr->symtree->n.sym->name,
    9609              :                                  &a->expr->where, &n_null->where);
    9610              :                     break;
    9611              :                   }
    9612              :             }
    9613           68 :           gfc_namespace *prog_unit = ns;
    9614           87 :           while (prog_unit->parent)
    9615              :             prog_unit = prog_unit->parent;
    9616              :           gfc_namespace *fn_ns = ns;
    9617           72 :           while (fn_ns)
    9618              :             {
    9619           70 :               if (ns->proc_name
    9620           70 :                   && (ns->proc_name->attr.subroutine
    9621            6 :                       || ns->proc_name->attr.function))
    9622              :                 break;
    9623            4 :               fn_ns = fn_ns->parent;
    9624              :             }
    9625           68 :           if (missing_allocator
    9626           58 :               && !(prog_unit->omp_requires & OMP_REQ_DYNAMIC_ALLOCATORS)
    9627           58 :               && ((fn_ns && fn_ns->proc_name->attr.omp_declare_target)
    9628           55 :                   || omp_clauses->contained_in_target_construct))
    9629              :             {
    9630            6 :               if (code->op == EXEC_OMP_ALLOCATORS)
    9631            2 :                 gfc_error ("ALLOCATORS directive at %L inside a target region "
    9632              :                            "must specify an ALLOCATOR modifier for %qs",
    9633              :                            &code->loc, missing_allocator_sym->name);
    9634            4 :               else if (missing_allocator_sym)
    9635            2 :                 gfc_error ("ALLOCATE directive at %L inside a target region "
    9636              :                            "must specify an ALLOCATOR clause for %qs",
    9637              :                            &code->loc, missing_allocator_sym->name);
    9638              :               else
    9639            2 :                 gfc_error ("ALLOCATE directive at %L inside a target region "
    9640              :                            "must specify an ALLOCATOR clause", &code->loc);
    9641              :             }
    9642              : 
    9643              :         }
    9644              :     }
    9645              : 
    9646              :   /* OpenACC reductions.  */
    9647        32157 :   if (openacc)
    9648              :     {
    9649        14753 :       for (n = omp_clauses->lists[OMP_LIST_REDUCTION]; n; n = n->next)
    9650         2136 :         n->sym->mark = 0;
    9651              : 
    9652        14753 :       for (n = omp_clauses->lists[OMP_LIST_REDUCTION]; n; n = n->next)
    9653              :         {
    9654         2136 :           if (n->sym->mark)
    9655            0 :             gfc_error ("Symbol %qs present on multiple clauses at %L",
    9656              :                        n->sym->name, &n->where);
    9657              :           else
    9658         2136 :             n->sym->mark = 1;
    9659              : 
    9660              :           /* OpenACC does not support reductions on arrays.  */
    9661         2136 :           if (n->sym->as)
    9662           71 :             gfc_error ("Array %qs is not permitted in reduction at %L",
    9663              :                        n->sym->name, &n->where);
    9664              :         }
    9665              :     }
    9666              : 
    9667        32911 :   for (n = omp_clauses->lists[OMP_LIST_TO]; n; n = n->next)
    9668          754 :     n->sym->mark = 0;
    9669        33188 :   for (n = omp_clauses->lists[OMP_LIST_FROM]; n; n = n->next)
    9670         1031 :     if (n->expr == NULL)
    9671         1015 :       n->sym->mark = 1;
    9672        32911 :   for (n = omp_clauses->lists[OMP_LIST_TO]; n; n = n->next)
    9673              :     {
    9674          754 :       if (n->expr == NULL && n->sym->mark)
    9675            0 :         gfc_error ("Symbol %qs present on both FROM and TO clauses at %L",
    9676              :                    n->sym->name, &n->where);
    9677              :       else
    9678          754 :         n->sym->mark = 1;
    9679              :     }
    9680              : 
    9681              :   bool has_inscan = false, has_notinscan = false;
    9682      1286280 :   for (list = 0; list < OMP_LIST_NUM; list++)
    9683      1254123 :     if ((n = omp_clauses->lists[list]) != NULL)
    9684              :       {
    9685        28832 :         const char *name = clause_names[list];
    9686              : 
    9687        28832 :         switch (list)
    9688              :           {
    9689              :           case OMP_LIST_COPYIN:
    9690          267 :             for (; n != NULL; n = n->next)
    9691              :               {
    9692          170 :                 if (!n->sym->attr.threadprivate)
    9693            0 :                   gfc_error ("Non-THREADPRIVATE object %qs in COPYIN clause"
    9694              :                              " at %L", n->sym->name, &n->where);
    9695              :               }
    9696              :             break;
    9697           83 :           case OMP_LIST_COPYPRIVATE:
    9698           83 :             if (omp_clauses->nowait)
    9699            6 :               gfc_error ("NOWAIT clause must not be used with COPYPRIVATE "
    9700              :                          "clause at %L", &n->where);
    9701          376 :             for (; n != NULL; n = n->next)
    9702              :               {
    9703          293 :                 if (n->sym->as && n->sym->as->type == AS_ASSUMED_SIZE)
    9704            0 :                   gfc_error ("Assumed size array %qs in COPYPRIVATE clause "
    9705              :                              "at %L", n->sym->name, &n->where);
    9706          293 :                 if (n->sym->attr.pointer && n->sym->attr.intent == INTENT_IN)
    9707            1 :                   gfc_error ("INTENT(IN) POINTER %qs in COPYPRIVATE clause "
    9708              :                              "at %L", n->sym->name, &n->where);
    9709              :               }
    9710              :             break;
    9711              :           case OMP_LIST_SHARED:
    9712         2574 :             for (; n != NULL; n = n->next)
    9713              :               {
    9714         1624 :                 if (n->sym->attr.threadprivate)
    9715            0 :                   gfc_error ("THREADPRIVATE object %qs in SHARED clause at "
    9716              :                              "%L", n->sym->name, &n->where);
    9717         1624 :                 if (n->sym->attr.cray_pointee)
    9718            1 :                   gfc_error ("Cray pointee %qs in SHARED clause at %L",
    9719              :                             n->sym->name, &n->where);
    9720         1624 :                 if (n->sym->attr.associate_var)
    9721            8 :                   gfc_error ("Associate name %qs in SHARED clause at %L",
    9722            8 :                              n->sym->attr.select_type_temporary
    9723            4 :                              ? n->sym->assoc->target->symtree->n.sym->name
    9724              :                              : n->sym->name, &n->where);
    9725         1624 :                 if (omp_clauses->detach
    9726            1 :                     && n->sym == omp_clauses->detach->symtree->n.sym)
    9727            1 :                   gfc_error ("DETACH event handle %qs in SHARED clause at %L",
    9728              :                              n->sym->name, &n->where);
    9729              :               }
    9730              :             break;
    9731              :           case OMP_LIST_ALIGNED:
    9732          256 :             for (; n != NULL; n = n->next)
    9733              :               {
    9734          150 :                 if (!n->sym->attr.pointer
    9735           45 :                     && !n->sym->attr.allocatable
    9736           30 :                     && !n->sym->attr.cray_pointer
    9737           18 :                     && (n->sym->ts.type != BT_DERIVED
    9738           18 :                         || (n->sym->ts.u.derived->from_intmod
    9739              :                             != INTMOD_ISO_C_BINDING)
    9740           18 :                         || (n->sym->ts.u.derived->intmod_sym_id
    9741              :                             != ISOCBINDING_PTR)))
    9742            0 :                   gfc_error ("%qs in ALIGNED clause must be POINTER, "
    9743              :                              "ALLOCATABLE, Cray pointer or C_PTR at %L",
    9744              :                              n->sym->name, &n->where);
    9745          150 :                 else if (n->expr)
    9746              :                   {
    9747          147 :                     if (!gfc_resolve_expr (n->expr)
    9748          147 :                         || n->expr->ts.type != BT_INTEGER
    9749          146 :                         || n->expr->rank != 0
    9750          146 :                         || n->expr->expr_type != EXPR_CONSTANT
    9751          292 :                         || mpz_sgn (n->expr->value.integer) <= 0)
    9752            4 :                       gfc_error ("%qs in ALIGNED clause at %L requires a scalar"
    9753              :                                  " positive constant integer alignment "
    9754            4 :                                  "expression", n->sym->name, &n->where);
    9755              :                   }
    9756              :               }
    9757              :             break;
    9758              :           case OMP_LIST_AFFINITY:
    9759              :           case OMP_LIST_DEPEND:
    9760              :           case OMP_LIST_MAP:
    9761              :           case OMP_LIST_TO:
    9762              :           case OMP_LIST_FROM:
    9763              :           case OMP_LIST_CACHE:
    9764        32038 :             for (; n != NULL; n = n->next)
    9765              :               {
    9766        20159 :                 if ((list == OMP_LIST_DEPEND || list == OMP_LIST_AFFINITY)
    9767         1995 :                     && n->u2.ns && !n->u2.ns->resolved)
    9768              :                   {
    9769           53 :                     n->u2.ns->resolved = 1;
    9770           53 :                     for (gfc_symbol *sym = n->u2.ns->omp_affinity_iterators;
    9771          110 :                          sym; sym = sym->tlink)
    9772              :                       {
    9773           57 :                         gfc_constructor *c;
    9774           57 :                         c = gfc_constructor_first (sym->value->value.constructor);
    9775           57 :                         if (!gfc_resolve_expr (c->expr)
    9776           57 :                             || c->expr->ts.type != BT_INTEGER
    9777          112 :                             || c->expr->rank != 0)
    9778            2 :                           gfc_error ("Scalar integer expression for range begin"
    9779            2 :                                      " expected at %L", &c->expr->where);
    9780           57 :                         c = gfc_constructor_next (c);
    9781           57 :                         if (!gfc_resolve_expr (c->expr)
    9782           57 :                             || c->expr->ts.type != BT_INTEGER
    9783          112 :                             || c->expr->rank != 0)
    9784            2 :                           gfc_error ("Scalar integer expression for range end "
    9785            2 :                                      "expected at %L", &c->expr->where);
    9786           57 :                         c = gfc_constructor_next (c);
    9787           57 :                         if (c && (!gfc_resolve_expr (c->expr)
    9788           16 :                                   || c->expr->ts.type != BT_INTEGER
    9789           14 :                                   || c->expr->rank != 0))
    9790            2 :                           gfc_error ("Scalar integer expression for range step "
    9791            2 :                                      "expected at %L", &c->expr->where);
    9792           55 :                         else if (c
    9793           14 :                                  && c->expr->expr_type == EXPR_CONSTANT
    9794           12 :                                  && mpz_cmp_si (c->expr->value.integer, 0) == 0)
    9795            2 :                           gfc_error ("Nonzero range step expected at %L",
    9796              :                                      &c->expr->where);
    9797              :                       }
    9798              :                   }
    9799              : 
    9800         1995 :                 if (list == OMP_LIST_DEPEND)
    9801              :                   {
    9802         3193 :                     if (n->u.depend_doacross_op == OMP_DEPEND_SINK_FIRST
    9803              :                         || n->u.depend_doacross_op == OMP_DOACROSS_SINK_FIRST
    9804         1960 :                         || n->u.depend_doacross_op == OMP_DOACROSS_SINK)
    9805              :                       {
    9806         1233 :                         if (omp_clauses->doacross_source)
    9807              :                           {
    9808            0 :                             gfc_error ("Dependence-type SINK used together with"
    9809              :                                        " SOURCE on the same construct at %L",
    9810              :                                        &n->where);
    9811            0 :                             omp_clauses->doacross_source = false;
    9812              :                           }
    9813         1233 :                         else if (n->expr)
    9814              :                           {
    9815          571 :                             if (!gfc_resolve_expr (n->expr)
    9816          571 :                                 || n->expr->ts.type != BT_INTEGER
    9817         1142 :                                 || n->expr->rank != 0)
    9818            0 :                               gfc_error ("SINK addend not a constant integer "
    9819              :                                          "at %L", &n->where);
    9820              :                           }
    9821         1233 :                         if (n->sym == NULL
    9822            4 :                             && (n->expr == NULL
    9823            3 :                                 || mpz_cmp_si (n->expr->value.integer, -1) != 0))
    9824            2 :                           gfc_error ("omp_cur_iteration at %L requires %<-1%> "
    9825              :                                      "as logical offset", &n->where);
    9826         1233 :                         continue;
    9827              :                       }
    9828          727 :                     else if (n->u.depend_doacross_op == OMP_DEPEND_DEPOBJ
    9829           38 :                              && !n->expr
    9830           22 :                              && (n->sym->ts.type != BT_INTEGER
    9831           22 :                                  || n->sym->ts.kind
    9832           22 :                                     != 2 * gfc_index_integer_kind
    9833           22 :                                  || n->sym->attr.dimension))
    9834            0 :                       gfc_error ("Locator %qs at %L in DEPEND clause of depobj "
    9835              :                                  "type shall be a scalar integer of "
    9836              :                                  "OMP_DEPEND_KIND kind", n->sym->name,
    9837              :                                  &n->where);
    9838          727 :                     else if (n->u.depend_doacross_op == OMP_DEPEND_DEPOBJ
    9839           38 :                              && n->expr
    9840          743 :                              && (!gfc_resolve_expr (n->expr)
    9841           16 :                                  || n->expr->ts.type != BT_INTEGER
    9842           16 :                                  || n->expr->ts.kind
    9843           16 :                                     != 2 * gfc_index_integer_kind
    9844           16 :                                  || n->expr->rank != 0))
    9845            0 :                       gfc_error ("Locator at %L in DEPEND clause of depobj "
    9846              :                                  "type shall be a scalar integer of "
    9847            0 :                                  "OMP_DEPEND_KIND kind", &n->expr->where);
    9848              :                   }
    9849        18926 :                 gfc_ref *lastref = NULL, *lastslice = NULL;
    9850        18926 :                 bool resolved = false;
    9851        18926 :                 if (n->expr)
    9852              :                   {
    9853         6248 :                     lastref = n->expr->ref;
    9854         6248 :                     resolved = gfc_resolve_expr (n->expr);
    9855              : 
    9856              :                     /* Look through component refs to find last array
    9857              :                        reference.  */
    9858         6248 :                     if (resolved)
    9859              :                       {
    9860        15872 :                         for (gfc_ref *ref = n->expr->ref; ref; ref = ref->next)
    9861         9642 :                           if (ref->type == REF_COMPONENT
    9862              :                               || ref->type == REF_SUBSTRING
    9863         9642 :                               || ref->type == REF_INQUIRY)
    9864              :                             lastref = ref;
    9865         6462 :                           else if (ref->type == REF_ARRAY)
    9866              :                             {
    9867        13614 :                               for (int i = 0; i < ref->u.ar.dimen; i++)
    9868         7152 :                                 if (ref->u.ar.dimen_type[i] == DIMEN_RANGE)
    9869         6002 :                                   lastslice = ref;
    9870              : 
    9871              :                               lastref = ref;
    9872              :                             }
    9873              : 
    9874              :                         /* The "!$acc cache" directive allows rectangular
    9875              :                            subarrays to be specified, with some restrictions
    9876              :                            on the form of bounds (not implemented).
    9877              :                            Only raise an error here if we're really sure the
    9878              :                            array isn't contiguous.  An expression such as
    9879              :                            arr(-n:n,-n:n) could be contiguous even if it looks
    9880              :                            like it may not be.  */
    9881         6230 :                         if (code->op != EXEC_OACC_UPDATE
    9882         5448 :                             && list != OMP_LIST_CACHE
    9883         5448 :                             && list != OMP_LIST_DEPEND
    9884         5129 :                             && !gfc_is_simply_contiguous (n->expr, false, true)
    9885         1407 :                             && gfc_is_not_contiguous (n->expr)
    9886         6243 :                             && !(lastslice
    9887           13 :                                  && (lastslice->next
    9888            3 :                                      || lastslice->type != REF_ARRAY)))
    9889            3 :                           gfc_error ("Array is not contiguous at %L",
    9890              :                                      &n->where);
    9891              :                       }
    9892              :                   }
    9893        18926 :                 if (list == OMP_LIST_MAP
    9894        16278 :                     && (n->sym->attr.omp_groupprivate
    9895        16277 :                         || n->sym->attr.omp_declare_target_local))
    9896            2 :                   gfc_error ("%qs argument to MAP clause at %L must not be a "
    9897              :                              "device-local variable, including GROUPPRIVATE",
    9898              :                              n->sym->name, &n->where);
    9899        18926 :                 if (openacc
    9900        18926 :                     && list == OMP_LIST_MAP
    9901         9562 :                     && (n->u.map.op == OMP_MAP_ATTACH
    9902         9496 :                         || n->u.map.op == OMP_MAP_DETACH))
    9903              :                   {
    9904          109 :                     symbol_attribute attr;
    9905          109 :                     if (n->expr)
    9906           99 :                       attr = gfc_expr_attr (n->expr);
    9907              :                     else
    9908           10 :                       attr = n->sym->attr;
    9909          109 :                     if (!attr.pointer && !attr.allocatable)
    9910            7 :                       gfc_error ("%qs clause argument must be ALLOCATABLE or "
    9911              :                                  "a POINTER at %L",
    9912            7 :                                  (n->u.map.op == OMP_MAP_ATTACH) ? "attach"
    9913              :                                  : "detach", &n->where);
    9914              :                   }
    9915        18926 :                 if (lastref
    9916        12690 :                     || (n->expr
    9917           12 :                         && (!resolved || n->expr->expr_type != EXPR_VARIABLE)))
    9918              :                   {
    9919         6248 :                     if (!lastslice
    9920         6248 :                         && lastref
    9921          896 :                         && lastref->type == REF_SUBSTRING)
    9922           11 :                       gfc_error ("Unexpected substring reference in %s clause "
    9923              :                                  "at %L", name, &n->where);
    9924         6237 :                     else if (!lastslice
    9925              :                              && lastref
    9926          885 :                              && lastref->type == REF_INQUIRY)
    9927              :                       {
    9928           12 :                         gcc_assert (lastref->u.i == INQUIRY_RE
    9929              :                                     || lastref->u.i == INQUIRY_IM);
    9930           12 :                         gfc_error ("Unexpected complex-parts designator "
    9931              :                                    "reference in %s clause at %L",
    9932              :                                    name, &n->where);
    9933              :                       }
    9934         6225 :                     else if (!resolved
    9935         6207 :                              || n->expr->expr_type != EXPR_VARIABLE
    9936         6195 :                              || (lastslice
    9937         5340 :                                  && (lastslice->next
    9938         5324 :                                      || lastslice->type != REF_ARRAY)))
    9939           46 :                       gfc_error ("%qs in %s clause at %L is not a proper "
    9940           46 :                                  "array section", n->sym->name, name,
    9941              :                                  &n->where);
    9942              :                     else if (lastslice)
    9943              :                       {
    9944              :                         int i;
    9945              :                         gfc_array_ref *ar = &lastslice->u.ar;
    9946        11323 :                         for (i = 0; i < ar->dimen; i++)
    9947         6000 :                           if (ar->stride[i] && code->op != EXEC_OACC_UPDATE)
    9948              :                             {
    9949            1 :                               gfc_error ("Stride should not be specified for "
    9950              :                                          "array section in %s clause at %L",
    9951              :                                          name, &n->where);
    9952            1 :                               break;
    9953              :                             }
    9954         5999 :                           else if (ar->dimen_type[i] != DIMEN_ELEMENT
    9955         5999 :                                    && ar->dimen_type[i] != DIMEN_RANGE)
    9956              :                             {
    9957            0 :                               gfc_error ("%qs in %s clause at %L is not a "
    9958              :                                          "proper array section",
    9959            0 :                                          n->sym->name, name, &n->where);
    9960            0 :                               break;
    9961              :                             }
    9962         5999 :                           else if ((list == OMP_LIST_DEPEND
    9963              :                                     || list == OMP_LIST_AFFINITY)
    9964          160 :                                    && ar->start[i]
    9965          133 :                                    && ar->start[i]->expr_type == EXPR_CONSTANT
    9966           97 :                                    && ar->end[i]
    9967           72 :                                    && ar->end[i]->expr_type == EXPR_CONSTANT
    9968           72 :                                    && mpz_cmp (ar->start[i]->value.integer,
    9969           72 :                                                ar->end[i]->value.integer) > 0)
    9970              :                             {
    9971            0 :                               gfc_error ("%qs in %s clause at %L is a "
    9972              :                                          "zero size array section",
    9973            0 :                                          n->sym->name,
    9974              :                                          list == OMP_LIST_DEPEND
    9975              :                                          ? "DEPEND" : "AFFINITY", &n->where);
    9976            0 :                               break;
    9977              :                             }
    9978              :                       }
    9979              :                   }
    9980        12678 :                 else if (openacc)
    9981              :                   {
    9982         5906 :                     if (list == OMP_LIST_MAP
    9983         5891 :                         && n->u.map.op == OMP_MAP_FORCE_DEVICEPTR)
    9984           65 :                       resolve_oacc_deviceptr_clause (n->sym, n->where, name);
    9985              :                     else
    9986         5841 :                       resolve_oacc_data_clauses (n->sym, n->where, name);
    9987              :                   }
    9988         6772 :                 else if (list != OMP_LIST_DEPEND
    9989         6279 :                          && n->sym->as
    9990         3007 :                          && n->sym->as->type == AS_ASSUMED_SIZE)
    9991            5 :                   gfc_error ("Assumed size array %qs in %s clause at %L",
    9992              :                              n->sym->name, name, &n->where);
    9993        18926 :                 if (list == OMP_LIST_MAP && !openacc)
    9994         6716 :                   switch (code->op)
    9995              :                     {
    9996         5592 :                     case EXEC_OMP_TARGET:
    9997         5592 :                     case EXEC_OMP_TARGET_PARALLEL:
    9998         5592 :                     case EXEC_OMP_TARGET_PARALLEL_DO:
    9999         5592 :                     case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
   10000         5592 :                     case EXEC_OMP_TARGET_PARALLEL_LOOP:
   10001         5592 :                     case EXEC_OMP_TARGET_SIMD:
   10002         5592 :                     case EXEC_OMP_TARGET_TEAMS:
   10003         5592 :                     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
   10004         5592 :                     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
   10005         5592 :                     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
   10006         5592 :                     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
   10007         5592 :                     case EXEC_OMP_TARGET_TEAMS_LOOP:
   10008         5592 :                     case EXEC_OMP_TARGET_DATA:
   10009         5592 :                       switch (n->u.map.op)
   10010              :                         {
   10011              :                         case OMP_MAP_TO:
   10012              :                         case OMP_MAP_ALWAYS_TO:
   10013              :                         case OMP_MAP_PRESENT_TO:
   10014              :                         case OMP_MAP_ALWAYS_PRESENT_TO:
   10015              :                         case OMP_MAP_FROM:
   10016              :                         case OMP_MAP_ALWAYS_FROM:
   10017              :                         case OMP_MAP_PRESENT_FROM:
   10018              :                         case OMP_MAP_ALWAYS_PRESENT_FROM:
   10019              :                         case OMP_MAP_TOFROM:
   10020              :                         case OMP_MAP_ALWAYS_TOFROM:
   10021              :                         case OMP_MAP_PRESENT_TOFROM:
   10022              :                         case OMP_MAP_ALWAYS_PRESENT_TOFROM:
   10023              :                         case OMP_MAP_ALLOC:
   10024              :                         case OMP_MAP_PRESENT_ALLOC:
   10025              :                           break;
   10026            2 :                         default:
   10027            2 :                           gfc_error ("TARGET%s with map-type other than TO, "
   10028              :                                      "FROM, TOFROM, or ALLOC on MAP clause "
   10029              :                                      "at %L",
   10030              :                                      code->op == EXEC_OMP_TARGET_DATA
   10031              :                                      ? " DATA" : "", &n->where);
   10032            2 :                           break;
   10033              :                         }
   10034              :                       break;
   10035          625 :                     case EXEC_OMP_TARGET_ENTER_DATA:
   10036          625 :                       switch (n->u.map.op)
   10037              :                         {
   10038              :                         case OMP_MAP_TO:
   10039              :                         case OMP_MAP_ALWAYS_TO:
   10040              :                         case OMP_MAP_PRESENT_TO:
   10041              :                         case OMP_MAP_ALWAYS_PRESENT_TO:
   10042              :                         case OMP_MAP_ALLOC:
   10043              :                         case OMP_MAP_PRESENT_ALLOC:
   10044              :                           break;
   10045          176 :                         case OMP_MAP_TOFROM:
   10046          176 :                           n->u.map.op = OMP_MAP_TO;
   10047          176 :                           break;
   10048            3 :                         case OMP_MAP_ALWAYS_TOFROM:
   10049            3 :                           n->u.map.op = OMP_MAP_ALWAYS_TO;
   10050            3 :                           break;
   10051            2 :                         case OMP_MAP_PRESENT_TOFROM:
   10052            2 :                           n->u.map.op = OMP_MAP_PRESENT_TO;
   10053            2 :                           break;
   10054            2 :                         case OMP_MAP_ALWAYS_PRESENT_TOFROM:
   10055            2 :                           n->u.map.op = OMP_MAP_ALWAYS_PRESENT_TO;
   10056            2 :                           break;
   10057            2 :                         default:
   10058            2 :                           gfc_error ("TARGET ENTER DATA with map-type other "
   10059              :                                      "than TO, TOFROM or ALLOC on MAP clause "
   10060              :                                      "at %L", &n->where);
   10061            2 :                           break;
   10062              :                         }
   10063              :                       break;
   10064          499 :                     case EXEC_OMP_TARGET_EXIT_DATA:
   10065          499 :                       switch (n->u.map.op)
   10066              :                         {
   10067              :                         case OMP_MAP_FROM:
   10068              :                         case OMP_MAP_ALWAYS_FROM:
   10069              :                         case OMP_MAP_PRESENT_FROM:
   10070              :                         case OMP_MAP_ALWAYS_PRESENT_FROM:
   10071              :                         case OMP_MAP_RELEASE:
   10072              :                         case OMP_MAP_DELETE:
   10073              :                           break;
   10074          132 :                         case OMP_MAP_TOFROM:
   10075          132 :                           n->u.map.op = OMP_MAP_FROM;
   10076          132 :                           break;
   10077            1 :                         case OMP_MAP_ALWAYS_TOFROM:
   10078            1 :                           n->u.map.op = OMP_MAP_ALWAYS_FROM;
   10079            1 :                           break;
   10080            0 :                         case OMP_MAP_PRESENT_TOFROM:
   10081            0 :                           n->u.map.op = OMP_MAP_PRESENT_FROM;
   10082            0 :                           break;
   10083            0 :                         case OMP_MAP_ALWAYS_PRESENT_TOFROM:
   10084            0 :                           n->u.map.op = OMP_MAP_ALWAYS_PRESENT_FROM;
   10085            0 :                           break;
   10086            2 :                         default:
   10087            2 :                           gfc_error ("TARGET EXIT DATA with map-type other "
   10088              :                                      "than FROM, TOFROM, RELEASE, or DELETE on "
   10089              :                                      "MAP clause at %L", &n->where);
   10090            2 :                           break;
   10091              :                         }
   10092              :                       break;
   10093              :                     default:
   10094              :                       break;
   10095              :                     }
   10096              :               }
   10097              : 
   10098        11879 :             if (list != OMP_LIST_DEPEND)
   10099        29234 :               for (n = omp_clauses->lists[list]; n != NULL; n = n->next)
   10100              :                 {
   10101        18199 :                   n->sym->attr.referenced = 1;
   10102        18199 :                   if (n->sym->attr.threadprivate)
   10103            1 :                     gfc_error ("THREADPRIVATE object %qs in %s clause at %L",
   10104              :                                n->sym->name, name, &n->where);
   10105        18199 :                   if (n->sym->attr.cray_pointee)
   10106           14 :                     gfc_error ("Cray pointee %qs in %s clause at %L",
   10107              :                                n->sym->name, name, &n->where);
   10108              :                 }
   10109              :             break;
   10110              :           case OMP_LIST_IS_DEVICE_PTR:
   10111              :             last = NULL;
   10112          377 :             for (n = omp_clauses->lists[list]; n != NULL; )
   10113              :               {
   10114          257 :                 if ((n->sym->ts.type != BT_DERIVED
   10115           71 :                      || !n->sym->ts.u.derived->ts.is_iso_c
   10116           71 :                      || (n->sym->ts.u.derived->intmod_sym_id
   10117              :                          != ISOCBINDING_PTR))
   10118          187 :                     && code->op == EXEC_OMP_DISPATCH)
   10119              :                   /* Non-TARGET (i.e. DISPATCH) requires a C_PTR.  */
   10120            3 :                   gfc_error ("List item %qs in %s clause at %L must be of "
   10121              :                              "TYPE(C_PTR)", n->sym->name, name, &n->where);
   10122          254 :                 else if (n->sym->ts.type != BT_DERIVED
   10123           70 :                          || !n->sym->ts.u.derived->ts.is_iso_c
   10124           70 :                          || (n->sym->ts.u.derived->intmod_sym_id
   10125              :                              != ISOCBINDING_PTR))
   10126              :                   {
   10127              :                     /* For TARGET, non-C_PTR are deprecated and handled as
   10128              :                        has_device_addr.  */
   10129          184 :                     gfc_warning (OPT_Wdeprecated_openmp,
   10130              :                                  "Non-C_PTR type argument at %L is deprecated, "
   10131              :                                  "use HAS_DEVICE_ADDR", &n->where);
   10132          184 :                     gfc_omp_namelist *n2 = n;
   10133          184 :                     n = n->next;
   10134          184 :                     if (last)
   10135            0 :                       last->next = n;
   10136              :                     else
   10137          184 :                       omp_clauses->lists[list] = n;
   10138          184 :                     n2->next = omp_clauses->lists[OMP_LIST_HAS_DEVICE_ADDR];
   10139          184 :                     omp_clauses->lists[OMP_LIST_HAS_DEVICE_ADDR] = n2;
   10140          184 :                     continue;
   10141          184 :                   }
   10142           73 :                 last = n;
   10143           73 :                 n = n->next;
   10144              :               }
   10145              :             break;
   10146              :           case OMP_LIST_HAS_DEVICE_ADDR:
   10147              :           case OMP_LIST_USE_DEVICE_ADDR:
   10148              :             break;
   10149              :           case OMP_LIST_USE_DEVICE_PTR:
   10150              :             /* Non-C_PTR are deprecated and handled as use_device_ADDR.  */
   10151              :             last = NULL;
   10152          475 :             for (n = omp_clauses->lists[list]; n != NULL; )
   10153              :               {
   10154          312 :                 gfc_omp_namelist *n2 = n;
   10155          312 :                 if (n->sym->ts.type != BT_DERIVED
   10156           18 :                     || !n->sym->ts.u.derived->ts.is_iso_c)
   10157              :                   {
   10158          294 :                     gfc_warning (OPT_Wdeprecated_openmp,
   10159              :                                  "Non-C_PTR type argument at %L is "
   10160              :                                  "deprecated, use USE_DEVICE_ADDR", &n->where);
   10161          294 :                     n = n->next;
   10162          294 :                     if (last)
   10163            0 :                       last->next = n;
   10164              :                     else
   10165          294 :                       omp_clauses->lists[list] = n;
   10166          294 :                     n2->next = omp_clauses->lists[OMP_LIST_USE_DEVICE_ADDR];
   10167          294 :                     omp_clauses->lists[OMP_LIST_USE_DEVICE_ADDR] = n2;
   10168          294 :                     continue;
   10169              :                   }
   10170           18 :                 last = n;
   10171           18 :                 n = n->next;
   10172              :               }
   10173              :             break;
   10174           48 :           case OMP_LIST_USES_ALLOCATORS:
   10175           48 :             {
   10176           48 :               if (n != NULL
   10177           48 :                   && n->u.memspace_sym
   10178           14 :                   && (n->u.memspace_sym->attr.flavor != FL_PARAMETER
   10179           13 :                       || n->u.memspace_sym->ts.type != BT_INTEGER
   10180           13 :                       || n->u.memspace_sym->ts.kind != gfc_c_intptr_kind
   10181           13 :                       || n->u.memspace_sym->attr.dimension
   10182           13 :                       || (!startswith (n->u.memspace_sym->name, "omp_")
   10183            0 :                           && !startswith (n->u.memspace_sym->name, "ompx_"))
   10184           13 :                       || !endswith (n->u.memspace_sym->name, "_mem_space")))
   10185            2 :                 gfc_error ("Memspace %qs at %L in USES_ALLOCATORS must be "
   10186              :                            "a predefined memory space",
   10187              :                            n->u.memspace_sym->name, &n->where);
   10188          144 :               for (; n != NULL; n = n->next)
   10189              :                 {
   10190          102 :                   if (n->sym->ts.type != BT_INTEGER
   10191          102 :                       || n->sym->ts.kind != gfc_c_intptr_kind
   10192          101 :                       || n->sym->attr.dimension)
   10193            2 :                     gfc_error ("Allocator %qs at %L in USES_ALLOCATORS must "
   10194              :                                "be a scalar integer of kind "
   10195              :                                "%<omp_allocator_handle_kind%>", n->sym->name,
   10196              :                                &n->where);
   10197          100 :                   else if (n->sym->attr.flavor != FL_VARIABLE
   10198           47 :                            && strcmp (n->sym->name, "omp_null_allocator") != 0
   10199          144 :                            && ((!startswith (n->sym->name, "omp_")
   10200            1 :                                 && !startswith (n->sym->name, "ompx_"))
   10201           43 :                                || !endswith (n->sym->name, "_mem_alloc")))
   10202            2 :                     gfc_error ("Allocator %qs at %L in USES_ALLOCATORS must "
   10203              :                                "either a variable or a predefined allocator",
   10204              :                                n->sym->name, &n->where);
   10205           98 :                   else if ((n->u.memspace_sym || n->u2.traits_sym)
   10206           47 :                            && n->sym->attr.flavor != FL_VARIABLE)
   10207            3 :                     gfc_error ("A memory space or traits array may not be "
   10208              :                                "specified for predefined allocator %qs at %L",
   10209              :                                n->sym->name, &n->where);
   10210          102 :                   if (n->u2.traits_sym
   10211           41 :                       && (n->u2.traits_sym->attr.flavor != FL_PARAMETER
   10212           39 :                           || !n->u2.traits_sym->attr.dimension
   10213           37 :                           || n->u2.traits_sym->as->rank != 1
   10214           37 :                           || n->u2.traits_sym->ts.type != BT_DERIVED
   10215           35 :                           || strcmp (n->u2.traits_sym->ts.u.derived->name,
   10216              :                                      "omp_alloctrait") != 0))
   10217              :                     {
   10218            6 :                       gfc_error ("Traits array %qs in USES_ALLOCATORS %L must "
   10219              :                                  "be a one-dimensional named constant array of "
   10220              :                                  "type %<omp_alloctrait%>",
   10221              :                                  n->u2.traits_sym->name, &n->where);
   10222            6 :                       break;
   10223              :                     }
   10224              :                 }
   10225              :               break;
   10226              :             }
   10227              :           default:
   10228        34580 :             for (; n != NULL; n = n->next)
   10229              :               {
   10230        20248 :                 if (n->sym == NULL)
   10231              :                   {
   10232           26 :                     gcc_assert (code->op == EXEC_OMP_ALLOCATORS
   10233              :                                 || code->op == EXEC_OMP_ALLOCATE);
   10234           26 :                     continue;
   10235              :                   }
   10236        20222 :                 bool bad = false;
   10237        20222 :                 bool is_reduction = (list == OMP_LIST_REDUCTION
   10238              :                                      || list == OMP_LIST_REDUCTION_INSCAN
   10239              :                                      || list == OMP_LIST_REDUCTION_TASK
   10240              :                                      || list == OMP_LIST_IN_REDUCTION
   10241        20222 :                                      || list == OMP_LIST_TASK_REDUCTION);
   10242        20222 :                 if (list == OMP_LIST_REDUCTION_INSCAN)
   10243              :                   has_inscan = true;
   10244        20150 :                 else if (is_reduction)
   10245         4733 :                   has_notinscan = true;
   10246        20222 :                 if (has_inscan && has_notinscan && is_reduction)
   10247              :                   {
   10248            3 :                     gfc_error ("%<inscan%> and non-%<inscan%> %<reduction%> "
   10249              :                                "clauses on the same construct at %L",
   10250              :                                &n->where);
   10251            3 :                     break;
   10252              :                   }
   10253        20219 :                 if (n->sym->attr.threadprivate)
   10254            1 :                   gfc_error ("THREADPRIVATE object %qs in %s clause at %L",
   10255              :                              n->sym->name, name, &n->where);
   10256        20219 :                 if (n->sym->attr.cray_pointee)
   10257           14 :                   gfc_error ("Cray pointee %qs in %s clause at %L",
   10258              :                             n->sym->name, name, &n->where);
   10259        20219 :                 if (n->sym->attr.associate_var)
   10260           22 :                   gfc_error ("Associate name %qs in %s clause at %L",
   10261           22 :                              n->sym->attr.select_type_temporary
   10262            4 :                              ? n->sym->assoc->target->symtree->n.sym->name
   10263              :                              : n->sym->name, name, &n->where);
   10264        20219 :                 if (list != OMP_LIST_PRIVATE && is_reduction)
   10265              :                   {
   10266         4802 :                     if (n->sym->attr.proc_pointer)
   10267            1 :                       gfc_error ("Procedure pointer %qs in %s clause at %L",
   10268              :                                  n->sym->name, name, &n->where);
   10269         4802 :                     if (n->sym->attr.pointer)
   10270            3 :                       gfc_error ("POINTER object %qs in %s clause at %L",
   10271              :                                  n->sym->name, name, &n->where);
   10272         4802 :                     if (n->sym->attr.cray_pointer)
   10273            5 :                       gfc_error ("Cray pointer %qs in %s clause at %L",
   10274              :                                  n->sym->name, name, &n->where);
   10275              :                   }
   10276        20219 :                 if (code
   10277        20219 :                     && (oacc_is_loop (code)
   10278              :                         || code->op == EXEC_OACC_PARALLEL
   10279              :                         || code->op == EXEC_OACC_SERIAL))
   10280         8737 :                   check_array_not_assumed (n->sym, n->where, name);
   10281        11482 :                 else if (list != OMP_LIST_UNIFORM
   10282        11365 :                          && n->sym->as && n->sym->as->type == AS_ASSUMED_SIZE)
   10283            2 :                   gfc_error ("Assumed size array %qs in %s clause at %L",
   10284              :                              n->sym->name, name, &n->where);
   10285        20219 :                 if (n->sym->attr.in_namelist && !is_reduction)
   10286            0 :                   gfc_error ("Variable %qs in %s clause is used in "
   10287              :                              "NAMELIST statement at %L",
   10288              :                              n->sym->name, name, &n->where);
   10289        20219 :                 if (n->sym->attr.pointer && n->sym->attr.intent == INTENT_IN)
   10290            3 :                   switch (list)
   10291              :                     {
   10292            3 :                     case OMP_LIST_PRIVATE:
   10293            3 :                     case OMP_LIST_LASTPRIVATE:
   10294            3 :                     case OMP_LIST_LINEAR:
   10295              :                     /* case OMP_LIST_REDUCTION: */
   10296            3 :                       gfc_error ("INTENT(IN) POINTER %qs in %s clause at %L",
   10297              :                                  n->sym->name, name, &n->where);
   10298            3 :                       break;
   10299              :                     default:
   10300              :                       break;
   10301              :                     }
   10302        20219 :                 if (omp_clauses->detach
   10303            3 :                     && (list == OMP_LIST_PRIVATE
   10304              :                         || list == OMP_LIST_FIRSTPRIVATE
   10305              :                         || list == OMP_LIST_LASTPRIVATE)
   10306            3 :                     && n->sym == omp_clauses->detach->symtree->n.sym)
   10307            1 :                   gfc_error ("DETACH event handle %qs in %s clause at %L",
   10308              :                              n->sym->name, name, &n->where);
   10309              : 
   10310        20219 :                 if (!openacc
   10311        20219 :                     && (list == OMP_LIST_PRIVATE
   10312        20219 :                         || list == OMP_LIST_FIRSTPRIVATE)
   10313         4585 :                     && ((n->sym->ts.type == BT_DERIVED
   10314          158 :                          && n->sym->ts.u.derived->attr.alloc_comp)
   10315         4475 :                         || n->sym->ts.type == BT_CLASS))
   10316          158 :                   switch (code->op)
   10317              :                     {
   10318            8 :                     case EXEC_OMP_TARGET:
   10319            8 :                     case EXEC_OMP_TARGET_PARALLEL:
   10320            8 :                     case EXEC_OMP_TARGET_PARALLEL_DO:
   10321            8 :                     case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
   10322            8 :                     case EXEC_OMP_TARGET_PARALLEL_LOOP:
   10323            8 :                     case EXEC_OMP_TARGET_SIMD:
   10324            8 :                     case EXEC_OMP_TARGET_TEAMS:
   10325            8 :                     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
   10326            8 :                     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
   10327            8 :                     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
   10328            8 :                     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
   10329            8 :                     case EXEC_OMP_TARGET_TEAMS_LOOP:
   10330            8 :                       if (n->sym->ts.type == BT_DERIVED
   10331            2 :                           && n->sym->ts.u.derived->attr.alloc_comp)
   10332            3 :                         gfc_error ("Sorry, list item %qs at %L with allocatable"
   10333              :                                    " components is not yet supported in %s "
   10334              :                                    "clause", n->sym->name, &n->where,
   10335              :                                    list == OMP_LIST_PRIVATE ? "PRIVATE"
   10336              :                                                             : "FIRSTPRIVATE");
   10337              :                       else
   10338            9 :                         gfc_error ("Polymorphic list item %qs at %L in %s "
   10339              :                                    "clause has unspecified behavior and "
   10340              :                                    "unsupported", n->sym->name, &n->where,
   10341              :                                    list == OMP_LIST_PRIVATE ? "PRIVATE"
   10342              :                                                             : "FIRSTPRIVATE");
   10343              :                       break;
   10344              :                     default:
   10345              :                       break;
   10346              :                     }
   10347              : 
   10348        20219 :                 switch (list)
   10349              :                   {
   10350          103 :                   case OMP_LIST_REDUCTION_TASK:
   10351          103 :                     if (code
   10352          103 :                         && (code->op == EXEC_OMP_LOOP
   10353              :                             || code->op == EXEC_OMP_TASKLOOP
   10354              :                             || code->op == EXEC_OMP_TASKLOOP_SIMD
   10355              :                             || code->op == EXEC_OMP_MASKED_TASKLOOP
   10356              :                             || code->op == EXEC_OMP_MASKED_TASKLOOP_SIMD
   10357              :                             || code->op == EXEC_OMP_MASTER_TASKLOOP
   10358              :                             || code->op == EXEC_OMP_MASTER_TASKLOOP_SIMD
   10359              :                             || code->op == EXEC_OMP_PARALLEL_LOOP
   10360              :                             || code->op == EXEC_OMP_PARALLEL_MASKED_TASKLOOP
   10361              :                             || code->op == EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD
   10362              :                             || code->op == EXEC_OMP_PARALLEL_MASTER_TASKLOOP
   10363              :                             || code->op == EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD
   10364              :                             || code->op == EXEC_OMP_TARGET_PARALLEL_LOOP
   10365              :                             || code->op == EXEC_OMP_TARGET_TEAMS_LOOP
   10366              :                             || code->op == EXEC_OMP_TEAMS
   10367              :                             || code->op == EXEC_OMP_TEAMS_DISTRIBUTE
   10368              :                             || code->op == EXEC_OMP_TEAMS_LOOP))
   10369              :                       {
   10370           17 :                         gfc_error ("Only DEFAULT permitted as reduction-"
   10371              :                                    "modifier in REDUCTION clause at %L",
   10372              :                                    &n->where);
   10373           17 :                         break;
   10374              :                       }
   10375         4785 :                     gcc_fallthrough ();
   10376         4785 :                   case OMP_LIST_REDUCTION:
   10377         4785 :                   case OMP_LIST_IN_REDUCTION:
   10378         4785 :                   case OMP_LIST_TASK_REDUCTION:
   10379         4785 :                   case OMP_LIST_REDUCTION_INSCAN:
   10380         4785 :                     switch (n->u.reduction_op)
   10381              :                       {
   10382         2651 :                       case OMP_REDUCTION_PLUS:
   10383         2651 :                       case OMP_REDUCTION_TIMES:
   10384         2651 :                       case OMP_REDUCTION_MINUS:
   10385         2651 :                         if (!gfc_numeric_ts (&n->sym->ts))
   10386              :                           bad = true;
   10387              :                         break;
   10388         1112 :                       case OMP_REDUCTION_AND:
   10389         1112 :                       case OMP_REDUCTION_OR:
   10390         1112 :                       case OMP_REDUCTION_EQV:
   10391         1112 :                       case OMP_REDUCTION_NEQV:
   10392         1112 :                         if (n->sym->ts.type != BT_LOGICAL)
   10393              :                           bad = true;
   10394              :                         break;
   10395          480 :                       case OMP_REDUCTION_MAX:
   10396          480 :                       case OMP_REDUCTION_MIN:
   10397          480 :                         if (n->sym->ts.type != BT_INTEGER
   10398          212 :                             && n->sym->ts.type != BT_REAL)
   10399              :                           bad = true;
   10400              :                         break;
   10401          192 :                       case OMP_REDUCTION_IAND:
   10402          192 :                       case OMP_REDUCTION_IOR:
   10403          192 :                       case OMP_REDUCTION_IEOR:
   10404          192 :                         if (n->sym->ts.type != BT_INTEGER)
   10405              :                           bad = true;
   10406              :                         break;
   10407              :                       case OMP_REDUCTION_USER:
   10408              :                         bad = true;
   10409              :                         break;
   10410              :                       default:
   10411              :                         break;
   10412              :                       }
   10413              :                     if (!bad)
   10414         4214 :                       n->u2.udr = NULL;
   10415              :                     else
   10416              :                       {
   10417          571 :                         const char *udr_name = NULL;
   10418          571 :                         if (n->u2.udr)
   10419              :                           {
   10420          467 :                             udr_name = n->u2.udr->udr->name;
   10421          467 :                             n->u2.udr->udr
   10422          934 :                               = gfc_find_omp_udr (NULL, udr_name,
   10423          467 :                                                   &n->sym->ts);
   10424          467 :                             if (n->u2.udr->udr == NULL)
   10425              :                               {
   10426            0 :                                 free (n->u2.udr);
   10427            0 :                                 n->u2.udr = NULL;
   10428              :                               }
   10429              :                           }
   10430          571 :                         if (n->u2.udr == NULL)
   10431              :                           {
   10432          104 :                             if (udr_name == NULL)
   10433          104 :                               switch (n->u.reduction_op)
   10434              :                                 {
   10435           50 :                                 case OMP_REDUCTION_PLUS:
   10436           50 :                                 case OMP_REDUCTION_TIMES:
   10437           50 :                                 case OMP_REDUCTION_MINUS:
   10438           50 :                                 case OMP_REDUCTION_AND:
   10439           50 :                                 case OMP_REDUCTION_OR:
   10440           50 :                                 case OMP_REDUCTION_EQV:
   10441           50 :                                 case OMP_REDUCTION_NEQV:
   10442           50 :                                   udr_name = gfc_op2string ((gfc_intrinsic_op)
   10443              :                                                             n->u.reduction_op);
   10444           50 :                                   break;
   10445              :                                 case OMP_REDUCTION_MAX:
   10446              :                                   udr_name = "max";
   10447              :                                   break;
   10448            9 :                                 case OMP_REDUCTION_MIN:
   10449            9 :                                   udr_name = "min";
   10450            9 :                                   break;
   10451           12 :                                 case OMP_REDUCTION_IAND:
   10452           12 :                                   udr_name = "iand";
   10453           12 :                                   break;
   10454           12 :                                 case OMP_REDUCTION_IOR:
   10455           12 :                                   udr_name = "ior";
   10456           12 :                                   break;
   10457            9 :                                 case OMP_REDUCTION_IEOR:
   10458            9 :                                   udr_name = "ieor";
   10459            9 :                                   break;
   10460            0 :                                 default:
   10461            0 :                                   gcc_unreachable ();
   10462              :                                 }
   10463          104 :                             gfc_error ("!$OMP DECLARE REDUCTION %s not found "
   10464              :                                        "for type %s at %L", udr_name,
   10465          104 :                                        gfc_typename (&n->sym->ts), &n->where);
   10466              :                           }
   10467              :                         else
   10468              :                           {
   10469          467 :                             gfc_omp_udr *udr = n->u2.udr->udr;
   10470          467 :                             n->u.reduction_op = OMP_REDUCTION_USER;
   10471          467 :                             n->u2.udr->combiner
   10472          934 :                               = resolve_omp_udr_clause (n, udr->combiner_ns,
   10473          467 :                                                         udr->omp_out,
   10474          467 :                                                         udr->omp_in);
   10475          467 :                             if (udr->initializer_ns)
   10476          330 :                               n->u2.udr->initializer
   10477          330 :                                 = resolve_omp_udr_clause (n,
   10478              :                                                           udr->initializer_ns,
   10479          330 :                                                           udr->omp_priv,
   10480          330 :                                                           udr->omp_orig);
   10481              :                           }
   10482              :                       }
   10483              :                     break;
   10484          873 :                   case OMP_LIST_LINEAR:
   10485          873 :                     if (code
   10486          726 :                         && n->u.linear.op != OMP_LINEAR_DEFAULT
   10487           23 :                         && n->u.linear.op != linear_op)
   10488              :                       {
   10489           23 :                         if (n->u.linear.old_modifier)
   10490              :                           {
   10491            9 :                             gfc_error ("LINEAR clause modifier used on DO or "
   10492              :                                        "SIMD construct at %L", &n->where);
   10493            9 :                             linear_op = n->u.linear.op;
   10494              :                           }
   10495           14 :                         else if (n->u.linear.op != OMP_LINEAR_VAL)
   10496              :                           {
   10497            6 :                             gfc_error ("LINEAR clause modifier other than VAL "
   10498              :                                        "used on DO or SIMD construct at %L",
   10499              :                                        &n->where);
   10500            6 :                             linear_op = n->u.linear.op;
   10501              :                           }
   10502              :                       }
   10503          850 :                     else if (n->u.linear.op != OMP_LINEAR_REF
   10504          800 :                              && n->sym->ts.type != BT_INTEGER)
   10505            1 :                       gfc_error ("LINEAR variable %qs must be INTEGER "
   10506              :                                  "at %L", n->sym->name, &n->where);
   10507          849 :                     else if ((n->u.linear.op == OMP_LINEAR_REF
   10508          799 :                               || n->u.linear.op == OMP_LINEAR_UVAL)
   10509           61 :                              && n->sym->attr.value)
   10510            0 :                       gfc_error ("LINEAR dummy argument %qs with VALUE "
   10511              :                                  "attribute with %s modifier at %L",
   10512              :                                  n->sym->name,
   10513              :                                  n->u.linear.op == OMP_LINEAR_REF
   10514              :                                  ? "REF" : "UVAL", &n->where);
   10515          849 :                     else if (n->expr)
   10516              :                       {
   10517          830 :                         gfc_expr *expr = n->expr;
   10518          830 :                         if (!gfc_resolve_expr (expr)
   10519          830 :                             || expr->ts.type != BT_INTEGER
   10520         1660 :                             || expr->rank != 0)
   10521            0 :                           gfc_error ("%qs in LINEAR clause at %L requires "
   10522              :                                      "a scalar integer linear-step expression",
   10523            0 :                                      n->sym->name, &n->where);
   10524          830 :                         else if (!code && expr->expr_type != EXPR_CONSTANT)
   10525              :                           {
   10526           11 :                             if (expr->expr_type == EXPR_VARIABLE
   10527            7 :                                 && expr->symtree->n.sym->attr.dummy
   10528            6 :                                 && expr->symtree->n.sym->ns == ns)
   10529              :                               {
   10530            6 :                                 gfc_omp_namelist *n2;
   10531            6 :                                 for (n2 = omp_clauses->lists[OMP_LIST_UNIFORM];
   10532            6 :                                      n2; n2 = n2->next)
   10533            6 :                                   if (n2->sym == expr->symtree->n.sym)
   10534              :                                     break;
   10535            6 :                                 if (n2)
   10536              :                                   break;
   10537              :                               }
   10538            5 :                             gfc_error ("%qs in LINEAR clause at %L requires "
   10539              :                                        "a constant integer linear-step "
   10540              :                                        "expression or dummy argument "
   10541              :                                        "specified in UNIFORM clause",
   10542            5 :                                        n->sym->name, &n->where);
   10543              :                           }
   10544              :                       }
   10545              :                     break;
   10546              :                   /* Workaround for PR middle-end/26316, nothing really needs
   10547              :                      to be done here for OMP_LIST_PRIVATE.  */
   10548         9374 :                   case OMP_LIST_PRIVATE:
   10549         9374 :                     gcc_assert (code && code->op != EXEC_NOP);
   10550              :                     break;
   10551           98 :                   case OMP_LIST_USE_DEVICE:
   10552           98 :                       if (n->sym->attr.allocatable
   10553           98 :                           || (n->sym->ts.type == BT_CLASS && CLASS_DATA (n->sym)
   10554            0 :                               && CLASS_DATA (n->sym)->attr.allocatable))
   10555            0 :                         gfc_error ("ALLOCATABLE object %qs in %s clause at %L",
   10556              :                                    n->sym->name, name, &n->where);
   10557           98 :                       if (n->sym->ts.type == BT_CLASS
   10558            0 :                           && CLASS_DATA (n->sym)
   10559            0 :                           && CLASS_DATA (n->sym)->attr.class_pointer)
   10560            0 :                         gfc_error ("POINTER object %qs of polymorphic type in "
   10561              :                                    "%s clause at %L", n->sym->name, name,
   10562              :                                    &n->where);
   10563           98 :                       if (n->sym->attr.cray_pointer)
   10564            2 :                         gfc_error ("Cray pointer object %qs in %s clause at %L",
   10565              :                                    n->sym->name, name, &n->where);
   10566           96 :                       else if (n->sym->attr.cray_pointee)
   10567            2 :                         gfc_error ("Cray pointee object %qs in %s clause at %L",
   10568              :                                    n->sym->name, name, &n->where);
   10569           94 :                       else if (n->sym->attr.flavor == FL_VARIABLE
   10570           93 :                                && !n->sym->as
   10571           54 :                                && !n->sym->attr.pointer)
   10572           13 :                         gfc_error ("%s clause variable %qs at %L is neither "
   10573              :                                    "a POINTER nor an array", name,
   10574              :                                    n->sym->name, &n->where);
   10575              :                       /* FALLTHRU */
   10576           98 :                   case OMP_LIST_DEVICE_RESIDENT:
   10577           98 :                     check_symbol_not_pointer (n->sym, n->where, name);
   10578           98 :                     check_array_not_assumed (n->sym, n->where, name);
   10579           98 :                     break;
   10580              :                   default:
   10581              :                     break;
   10582              :                   }
   10583              :               }
   10584              :             break;
   10585              :           }
   10586              :       }
   10587              :   /* OpenMP 5.1: use_device_ptr acts like use_device_addr, except for
   10588              :      type(c_ptr).  */
   10589        32157 :   if (omp_clauses->lists[OMP_LIST_USE_DEVICE_PTR])
   10590              :     {
   10591            9 :       gfc_omp_namelist *n_prev, *n_next, *n_addr;
   10592            9 :       n_addr = omp_clauses->lists[OMP_LIST_USE_DEVICE_ADDR];
   10593           28 :       for (; n_addr && n_addr->next; n_addr = n_addr->next)
   10594              :         ;
   10595              :       n_prev = NULL;
   10596              :       n = omp_clauses->lists[OMP_LIST_USE_DEVICE_PTR];
   10597           27 :       while (n)
   10598              :         {
   10599           18 :           n_next = n->next;
   10600           18 :           if (n->sym->ts.type != BT_DERIVED
   10601           18 :               || n->sym->ts.u.derived->ts.f90_type != BT_VOID)
   10602              :             {
   10603            0 :               n->next = NULL;
   10604            0 :               if (n_addr)
   10605            0 :                 n_addr->next = n;
   10606              :               else
   10607            0 :                 omp_clauses->lists[OMP_LIST_USE_DEVICE_ADDR] = n;
   10608            0 :               n_addr = n;
   10609            0 :               if (n_prev)
   10610            0 :                 n_prev->next = n_next;
   10611              :               else
   10612            0 :                 omp_clauses->lists[OMP_LIST_USE_DEVICE_PTR] = n_next;
   10613              :             }
   10614              :           else
   10615              :             n_prev = n;
   10616              :           n = n_next;
   10617              :         }
   10618              :     }
   10619        32157 :   if (omp_clauses->safelen_expr)
   10620           93 :     resolve_positive_int_expr (omp_clauses->safelen_expr, "SAFELEN");
   10621        32157 :   if (omp_clauses->simdlen_expr)
   10622          123 :     resolve_positive_int_expr (omp_clauses->simdlen_expr, "SIMDLEN");
   10623        32157 :   if (omp_clauses->num_teams_lower)
   10624           21 :     resolve_positive_int_expr (omp_clauses->num_teams_lower, "NUM_TEAMS");
   10625        32157 :   if (omp_clauses->num_teams_upper)
   10626          127 :     resolve_positive_int_expr (omp_clauses->num_teams_upper, "NUM_TEAMS");
   10627        32157 :   if (omp_clauses->num_teams_lower
   10628           21 :       && omp_clauses->num_teams_lower->expr_type == EXPR_CONSTANT
   10629            7 :       && omp_clauses->num_teams_upper->expr_type == EXPR_CONSTANT
   10630            7 :       && mpz_cmp (omp_clauses->num_teams_lower->value.integer,
   10631            7 :                   omp_clauses->num_teams_upper->value.integer) > 0)
   10632            2 :     gfc_warning (OPT_Wopenmp, "NUM_TEAMS lower bound at %L larger than upper "
   10633              :                  "bound at %L", &omp_clauses->num_teams_lower->where,
   10634              :                  &omp_clauses->num_teams_upper->where);
   10635        32157 :   if (omp_clauses->device)
   10636          331 :     resolve_scalar_int_expr (omp_clauses->device, "DEVICE");
   10637        32157 :   if (omp_clauses->filter)
   10638           42 :     resolve_nonnegative_int_expr (omp_clauses->filter, "FILTER");
   10639        32157 :   if (omp_clauses->hint)
   10640              :     {
   10641           42 :       resolve_scalar_int_expr (omp_clauses->hint, "HINT");
   10642           42 :     if (omp_clauses->hint->ts.type != BT_INTEGER
   10643           40 :         || omp_clauses->hint->expr_type != EXPR_CONSTANT
   10644           38 :         || mpz_sgn (omp_clauses->hint->value.integer) < 0)
   10645            5 :       gfc_error ("Value of HINT clause at %L shall be a valid "
   10646              :                  "constant hint expression", &omp_clauses->hint->where);
   10647              :     }
   10648        32157 :   if (omp_clauses->priority)
   10649           34 :     resolve_nonnegative_int_expr (omp_clauses->priority, "PRIORITY");
   10650        32157 :   if (omp_clauses->dist_chunk_size)
   10651              :     {
   10652           83 :       gfc_expr *expr = omp_clauses->dist_chunk_size;
   10653           83 :       if (!gfc_resolve_expr (expr)
   10654           83 :           || expr->ts.type != BT_INTEGER || expr->rank != 0)
   10655            0 :         gfc_error ("DIST_SCHEDULE clause's chunk_size at %L requires "
   10656              :                    "a scalar INTEGER expression", &expr->where);
   10657              :     }
   10658        32157 :   if (omp_clauses->thread_limit)
   10659           72 :     resolve_positive_int_expr (omp_clauses->thread_limit, "THREAD_LIMIT");
   10660        32157 :   if (omp_clauses->grainsize)
   10661           34 :     resolve_positive_int_expr (omp_clauses->grainsize, "GRAINSIZE");
   10662        32157 :   if (omp_clauses->num_tasks)
   10663           26 :     resolve_positive_int_expr (omp_clauses->num_tasks, "NUM_TASKS");
   10664        32157 :   if (omp_clauses->grainsize && omp_clauses->num_tasks)
   10665            1 :     gfc_error ("%<GRAINSIZE%> clause at %L must not be used together with "
   10666              :                "%<NUM_TASKS%> clause", &omp_clauses->grainsize->where);
   10667        32157 :   if (omp_clauses->lists[OMP_LIST_REDUCTION] && omp_clauses->nogroup)
   10668            1 :     gfc_error ("%<REDUCTION%> clause at %L must not be used together with "
   10669              :                "%<NOGROUP%> clause",
   10670              :                &omp_clauses->lists[OMP_LIST_REDUCTION]->where);
   10671        32157 :   if (omp_clauses->full && omp_clauses->partial)
   10672            0 :     gfc_error ("%<FULL%> clause at %C must not be used together with "
   10673              :                "%<PARTIAL%> clause");
   10674        32157 :   if (omp_clauses->async)
   10675          610 :     if (omp_clauses->async_expr)
   10676          610 :       resolve_scalar_int_expr (omp_clauses->async_expr, "ASYNC");
   10677        32157 :   if (omp_clauses->num_gangs_expr)
   10678          682 :     resolve_positive_int_expr (omp_clauses->num_gangs_expr, "NUM_GANGS");
   10679        32157 :   if (omp_clauses->num_workers_expr)
   10680          599 :     resolve_positive_int_expr (omp_clauses->num_workers_expr, "NUM_WORKERS");
   10681        32157 :   if (omp_clauses->vector_length_expr)
   10682          569 :     resolve_positive_int_expr (omp_clauses->vector_length_expr,
   10683              :                                "VECTOR_LENGTH");
   10684        32157 :   if (omp_clauses->gang_num_expr)
   10685          114 :     resolve_positive_int_expr (omp_clauses->gang_num_expr, "GANG");
   10686        32157 :   if (omp_clauses->gang_static_expr)
   10687           94 :     resolve_positive_int_expr (omp_clauses->gang_static_expr, "GANG");
   10688        32157 :   if (omp_clauses->worker_expr)
   10689          101 :     resolve_positive_int_expr (omp_clauses->worker_expr, "WORKER");
   10690        32157 :   if (omp_clauses->vector_expr)
   10691          132 :     resolve_positive_int_expr (omp_clauses->vector_expr, "VECTOR");
   10692        32496 :   for (el = omp_clauses->wait_list; el; el = el->next)
   10693          339 :     resolve_scalar_int_expr (el->expr, "WAIT");
   10694        32157 :   if (omp_clauses->collapse && omp_clauses->tile_list)
   10695            4 :     gfc_error ("Incompatible use of TILE and COLLAPSE at %L", &code->loc);
   10696        32157 :   if (omp_clauses->message)
   10697              :     {
   10698           45 :       gfc_expr *expr = omp_clauses->message;
   10699           45 :       if (!gfc_resolve_expr (expr)
   10700           45 :           || expr->ts.kind != gfc_default_character_kind
   10701           87 :           || expr->ts.type != BT_CHARACTER || expr->rank != 0)
   10702            4 :         gfc_error ("MESSAGE clause at %L requires a scalar default-kind "
   10703              :                    "CHARACTER expression", &expr->where);
   10704              :     }
   10705        32157 :   if (!openacc
   10706        32157 :       && code
   10707        19322 :       && omp_clauses->lists[OMP_LIST_MAP] == NULL
   10708        15865 :       && omp_clauses->lists[OMP_LIST_USE_DEVICE_PTR] == NULL
   10709        15862 :       && omp_clauses->lists[OMP_LIST_USE_DEVICE_ADDR] == NULL)
   10710              :     {
   10711        15839 :       const char *p = NULL;
   10712        15839 :       switch (code->op)
   10713              :         {
   10714            1 :         case EXEC_OMP_TARGET_ENTER_DATA: p = "TARGET ENTER DATA"; break;
   10715            1 :         case EXEC_OMP_TARGET_EXIT_DATA: p = "TARGET EXIT DATA"; break;
   10716              :         default: break;
   10717              :         }
   10718        15839 :       if (code->op == EXEC_OMP_TARGET_DATA)
   10719            1 :         gfc_error ("TARGET DATA must contain at least one MAP, USE_DEVICE_PTR, "
   10720              :                    "or USE_DEVICE_ADDR clause at %L", &code->loc);
   10721        15838 :       else if (p)
   10722            2 :         gfc_error ("%s must contain at least one MAP clause at %L",
   10723              :                    p, &code->loc);
   10724              :     }
   10725        32157 :   if (omp_clauses->sizes_list)
   10726              :     {
   10727              :       gfc_expr_list *el;
   10728          572 :       for (el = omp_clauses->sizes_list; el; el = el->next)
   10729              :         {
   10730          377 :           resolve_scalar_int_expr (el->expr, "SIZES");
   10731          377 :           if (el->expr->expr_type != EXPR_CONSTANT)
   10732            1 :             gfc_error ("SIZES requires constant expression at %L",
   10733              :                        &el->expr->where);
   10734          376 :           else if (el->expr->expr_type == EXPR_CONSTANT
   10735          376 :                    && el->expr->ts.type == BT_INTEGER
   10736          376 :                    && mpz_sgn (el->expr->value.integer) <= 0)
   10737            2 :             gfc_error ("INTEGER expression of %s clause at %L must be "
   10738              :                        "positive", "SIZES", &el->expr->where);
   10739              :         }
   10740              :     }
   10741              : 
   10742        32157 :   if (!openacc && omp_clauses->detach)
   10743              :     {
   10744          125 :       if (!gfc_resolve_expr (omp_clauses->detach)
   10745          125 :           || omp_clauses->detach->ts.type != BT_INTEGER
   10746          124 :           || omp_clauses->detach->ts.kind != gfc_c_intptr_kind
   10747          248 :           || omp_clauses->detach->rank != 0)
   10748            3 :         gfc_error ("%qs at %L should be a scalar of type "
   10749              :                    "integer(kind=omp_event_handle_kind)",
   10750            3 :                    omp_clauses->detach->symtree->n.sym->name,
   10751            3 :                    &omp_clauses->detach->where);
   10752          122 :       else if (omp_clauses->detach->symtree->n.sym->attr.dimension > 0)
   10753            1 :         gfc_error ("The event handle at %L must not be an array element",
   10754              :                    &omp_clauses->detach->where);
   10755          121 :       else if (omp_clauses->detach->symtree->n.sym->ts.type == BT_DERIVED
   10756          120 :                || omp_clauses->detach->symtree->n.sym->ts.type == BT_CLASS)
   10757            1 :         gfc_error ("The event handle at %L must not be part of "
   10758              :                    "a derived type or class", &omp_clauses->detach->where);
   10759              : 
   10760          125 :       if (omp_clauses->mergeable)
   10761            2 :         gfc_error ("%<DETACH%> clause at %L must not be used together with "
   10762            2 :                    "%<MERGEABLE%> clause", &omp_clauses->detach->where);
   10763              :     }
   10764              : 
   10765        12617 :   if (openacc
   10766        12617 :       && code->op == EXEC_OACC_HOST_DATA
   10767           60 :       && omp_clauses->lists[OMP_LIST_USE_DEVICE] == NULL)
   10768            1 :     gfc_error ("%<host_data%> construct at %L requires %<use_device%> clause",
   10769              :                &code->loc);
   10770              : 
   10771        32157 :   if (omp_clauses->assume)
   10772           16 :     gfc_resolve_omp_assumptions (omp_clauses->assume);
   10773              : }
   10774              : 
   10775              : 
   10776              : /* Return true if SYM is ever referenced in EXPR except in the SE node.  */
   10777              : 
   10778              : static bool
   10779         4991 : expr_references_sym (gfc_expr *e, gfc_symbol *s, gfc_expr *se)
   10780              : {
   10781         6617 :   gfc_actual_arglist *arg;
   10782         6617 :   if (e == NULL || e == se)
   10783              :     return false;
   10784         5366 :   switch (e->expr_type)
   10785              :     {
   10786         3120 :     case EXPR_CONSTANT:
   10787         3120 :     case EXPR_NULL:
   10788         3120 :     case EXPR_VARIABLE:
   10789         3120 :     case EXPR_STRUCTURE:
   10790         3120 :     case EXPR_ARRAY:
   10791         3120 :       if (e->symtree != NULL
   10792         1152 :           && e->symtree->n.sym == s)
   10793              :         return true;
   10794              :       return false;
   10795            0 :     case EXPR_SUBSTRING:
   10796            0 :       if (e->ref != NULL
   10797            0 :           && (expr_references_sym (e->ref->u.ss.start, s, se)
   10798            0 :               || expr_references_sym (e->ref->u.ss.end, s, se)))
   10799            0 :         return true;
   10800              :       return false;
   10801         1735 :     case EXPR_OP:
   10802         1735 :       if (expr_references_sym (e->value.op.op2, s, se))
   10803              :         return true;
   10804         1626 :       return expr_references_sym (e->value.op.op1, s, se);
   10805          511 :     case EXPR_FUNCTION:
   10806          896 :       for (arg = e->value.function.actual; arg; arg = arg->next)
   10807          586 :         if (expr_references_sym (arg->expr, s, se))
   10808              :           return true;
   10809              :       return false;
   10810            0 :     default:
   10811            0 :       gcc_unreachable ();
   10812              :     }
   10813              : }
   10814              : 
   10815              : 
   10816              : /* If EXPR is a conversion function that widens the type
   10817              :    if WIDENING is true or narrows the type if NARROW is true,
   10818              :    return the inner expression, otherwise return NULL.  */
   10819              : 
   10820              : static gfc_expr *
   10821         5911 : is_conversion (gfc_expr *expr, bool narrowing, bool widening)
   10822              : {
   10823         5911 :   gfc_typespec *ts1, *ts2;
   10824              : 
   10825         5911 :   if (expr->expr_type != EXPR_FUNCTION
   10826          917 :       || expr->value.function.isym == NULL
   10827          894 :       || expr->value.function.esym != NULL
   10828          894 :       || expr->value.function.isym->id != GFC_ISYM_CONVERSION
   10829          388 :       || (!narrowing && !widening))
   10830              :     return NULL;
   10831              : 
   10832          388 :   if (narrowing && widening)
   10833          267 :     return expr->value.function.actual->expr;
   10834              : 
   10835          121 :   if (widening)
   10836              :     {
   10837          121 :       ts1 = &expr->ts;
   10838          121 :       ts2 = &expr->value.function.actual->expr->ts;
   10839              :     }
   10840              :   else
   10841              :     {
   10842            0 :       ts1 = &expr->value.function.actual->expr->ts;
   10843            0 :       ts2 = &expr->ts;
   10844              :     }
   10845              : 
   10846          121 :   if (ts1->type > ts2->type
   10847           49 :       || (ts1->type == ts2->type && ts1->kind > ts2->kind))
   10848          121 :     return expr->value.function.actual->expr;
   10849              : 
   10850              :   return NULL;
   10851              : }
   10852              : 
   10853              : static bool
   10854         6855 : is_scalar_intrinsic_expr (gfc_expr *expr, bool must_be_var, bool conv_ok)
   10855              : {
   10856         6855 :   if (must_be_var
   10857         4020 :       && (expr->expr_type != EXPR_VARIABLE || !expr->symtree))
   10858              :     {
   10859           37 :       if (!conv_ok)
   10860              :         return false;
   10861           37 :       gfc_expr *conv = is_conversion (expr, true, true);
   10862           37 :       if (!conv)
   10863              :         return false;
   10864           36 :       if (conv->expr_type != EXPR_VARIABLE || !conv->symtree)
   10865              :         return false;
   10866              :     }
   10867         6852 :   return (expr->rank == 0
   10868         6848 :           && !gfc_is_coindexed (expr)
   10869        13700 :           && (expr->ts.type == BT_INTEGER
   10870              :               || expr->ts.type == BT_REAL
   10871              :               || expr->ts.type == BT_COMPLEX
   10872              :               || expr->ts.type == BT_LOGICAL));
   10873              : }
   10874              : 
   10875              : static void
   10876         2697 : resolve_omp_atomic (gfc_code *code)
   10877              : {
   10878         2697 :   gfc_code *atomic_code = code->block;
   10879         2697 :   gfc_symbol *var;
   10880         2697 :   gfc_expr *stmt_expr2, *capt_expr2;
   10881         2697 :   gfc_omp_atomic_op aop
   10882         2697 :     = (gfc_omp_atomic_op) (atomic_code->ext.omp_clauses->atomic_op
   10883              :                            & GFC_OMP_ATOMIC_MASK);
   10884         2697 :   gfc_code *stmt = NULL, *capture_stmt = NULL, *tailing_stmt = NULL;
   10885         2697 :   gfc_expr *comp_cond = NULL;
   10886         2697 :   locus *loc = NULL;
   10887              : 
   10888         2697 :   code = code->block->next;
   10889              :   /* resolve_blocks asserts this is initially EXEC_ASSIGN or EXEC_IF
   10890              :      If it changed to EXEC_NOP, assume an error has been emitted already.  */
   10891         2697 :   if (code->op == EXEC_NOP)
   10892              :     return;
   10893              : 
   10894         2696 :   if (atomic_code->ext.omp_clauses->compare
   10895          156 :       && atomic_code->ext.omp_clauses->capture)
   10896              :     {
   10897              :       /* Must be either "if (x == e) then; x = d; else; v = x; end if"
   10898              :          or "v = expr" followed/preceded by
   10899              :          "if (x == e) then; x = d; end if" or "if (x == e) x = d".  */
   10900          103 :       gfc_code *next = code;
   10901          103 :       if (code->op == EXEC_ASSIGN)
   10902              :         {
   10903           19 :           capture_stmt = code;
   10904           19 :           next = code->next;
   10905              :         }
   10906          103 :       if (next->op == EXEC_IF
   10907          103 :           && next->block
   10908          103 :           && next->block->op == EXEC_IF
   10909          103 :           && next->block->next
   10910          102 :           && next->block->next->op == EXEC_ASSIGN)
   10911              :         {
   10912          102 :           comp_cond = next->block->expr1;
   10913          102 :           stmt = next->block->next;
   10914          102 :           if (stmt->next)
   10915              :             {
   10916            0 :               loc = &stmt->loc;
   10917            0 :               goto unexpected;
   10918              :             }
   10919              :         }
   10920            1 :       else if (capture_stmt)
   10921              :         {
   10922            0 :           gfc_error ("Expected IF at %L in atomic compare capture",
   10923              :                      &next->loc);
   10924            0 :           return;
   10925              :         }
   10926          103 :       if (stmt && !capture_stmt && next->block->block)
   10927              :         {
   10928           64 :           if (next->block->block->expr1)
   10929              :             {
   10930            0 :               gfc_error ("Expected ELSE at %L in atomic compare capture",
   10931              :                          &next->block->block->expr1->where);
   10932            0 :               return;
   10933              :             }
   10934           64 :           if (!code->block->block->next
   10935           64 :               || code->block->block->next->op != EXEC_ASSIGN)
   10936              :             {
   10937            0 :               loc = (code->block->block->next ? &code->block->block->next->loc
   10938              :                                               : &code->block->block->loc);
   10939            0 :               goto unexpected;
   10940              :             }
   10941           64 :           capture_stmt = code->block->block->next;
   10942           64 :           if (capture_stmt->next)
   10943              :             {
   10944            0 :               loc = &capture_stmt->next->loc;
   10945            0 :               goto unexpected;
   10946              :             }
   10947              :         }
   10948          103 :       if (stmt && !capture_stmt && next->next->op == EXEC_ASSIGN)
   10949              :         capture_stmt = next->next;
   10950           84 :       else if (!capture_stmt)
   10951              :         {
   10952            1 :           loc = &code->loc;
   10953            1 :           goto unexpected;
   10954              :         }
   10955              :     }
   10956         2593 :   else if (atomic_code->ext.omp_clauses->compare)
   10957              :     {
   10958              :       /* Must be: "if (x == e) then; x = d; end if" or "if (x == e) x = d".  */
   10959           53 :       if (code->op == EXEC_IF
   10960           53 :           && code->block
   10961           53 :           && code->block->op == EXEC_IF
   10962           53 :           && code->block->next
   10963           51 :           && code->block->next->op == EXEC_ASSIGN)
   10964              :         {
   10965           51 :           comp_cond = code->block->expr1;
   10966           51 :           stmt = code->block->next;
   10967           51 :           if (stmt->next || code->block->block)
   10968              :             {
   10969            0 :               loc = stmt->next ? &stmt->next->loc : &code->block->block->loc;
   10970            0 :               goto unexpected;
   10971              :             }
   10972              :         }
   10973              :       else
   10974              :         {
   10975            2 :           loc = &code->loc;
   10976            2 :           goto unexpected;
   10977              :         }
   10978              :     }
   10979         2540 :   else if (atomic_code->ext.omp_clauses->capture)
   10980              :     {
   10981              :       /* Must be: "v = x" followed/preceded by "x = ...". */
   10982          489 :       if (code->op != EXEC_ASSIGN)
   10983            0 :         goto unexpected;
   10984          489 :       if (code->next->op != EXEC_ASSIGN)
   10985              :         {
   10986            0 :           loc = &code->next->loc;
   10987            0 :           goto unexpected;
   10988              :         }
   10989          489 :       gfc_expr *expr2, *expr2_next;
   10990          489 :       expr2 = is_conversion (code->expr2, true, true);
   10991          489 :       if (expr2 == NULL)
   10992          447 :         expr2 = code->expr2;
   10993          489 :       expr2_next = is_conversion (code->next->expr2, true, true);
   10994          489 :       if (expr2_next == NULL)
   10995          478 :         expr2_next = code->next->expr2;
   10996          489 :       if (code->expr1->expr_type == EXPR_VARIABLE
   10997          489 :           && code->next->expr1->expr_type == EXPR_VARIABLE
   10998          489 :           && expr2->expr_type == EXPR_VARIABLE
   10999          243 :           && expr2_next->expr_type == EXPR_VARIABLE)
   11000              :         {
   11001            1 :           if (code->expr1->symtree->n.sym == expr2_next->symtree->n.sym)
   11002              :             {
   11003              :               stmt = code;
   11004              :               capture_stmt = code->next;
   11005              :             }
   11006              :           else
   11007              :             {
   11008          489 :               capture_stmt = code;
   11009          489 :               stmt = code->next;
   11010              :             }
   11011              :         }
   11012          488 :       else if (expr2->expr_type == EXPR_VARIABLE)
   11013              :         {
   11014              :           capture_stmt = code;
   11015              :           stmt = code->next;
   11016              :         }
   11017              :       else
   11018              :         {
   11019          247 :           stmt = code;
   11020          247 :           capture_stmt = code->next;
   11021              :         }
   11022              :       /* Shall be NULL but can happen for invalid code. */
   11023          489 :       tailing_stmt = code->next->next;
   11024              :     }
   11025              :   else
   11026              :     {
   11027              :       /* x = ... */
   11028         2051 :       stmt = code;
   11029         2051 :       if (!atomic_code->ext.omp_clauses->compare && stmt->op != EXEC_ASSIGN)
   11030            1 :         goto unexpected;
   11031              :       /* Shall be NULL but can happen for invalid code. */
   11032         2050 :       tailing_stmt = code->next;
   11033              :     }
   11034              : 
   11035         2692 :   if (comp_cond)
   11036              :     {
   11037          153 :       if (comp_cond->expr_type != EXPR_OP
   11038          153 :           || (comp_cond->value.op.op != INTRINSIC_EQ
   11039              :               && comp_cond->value.op.op != INTRINSIC_EQ_OS
   11040              :               && comp_cond->value.op.op != INTRINSIC_EQV))
   11041              :         {
   11042            0 :           gfc_error ("Expected %<==%>, %<.EQ.%> or %<.EQV.%> atomic comparison "
   11043              :                      "expression at %L", &comp_cond->where);
   11044            0 :           return;
   11045              :         }
   11046          153 :       if (!is_scalar_intrinsic_expr (comp_cond->value.op.op1, true, true))
   11047              :         {
   11048            1 :           gfc_error ("Expected scalar intrinsic variable at %L in atomic "
   11049            1 :                      "comparison", &comp_cond->value.op.op1->where);
   11050            1 :           return;
   11051              :         }
   11052          152 :       if (!gfc_resolve_expr (comp_cond->value.op.op2))
   11053              :         return;
   11054          152 :       if (!is_scalar_intrinsic_expr (comp_cond->value.op.op2, false, false))
   11055              :         {
   11056            0 :           gfc_error ("Expected scalar intrinsic expression at %L in atomic "
   11057            0 :                      "comparison", &comp_cond->value.op.op1->where);
   11058            0 :           return;
   11059              :         }
   11060              :     }
   11061              : 
   11062         2691 :   if (!is_scalar_intrinsic_expr (stmt->expr1, true, false))
   11063              :     {
   11064            4 :       gfc_error ("!$OMP ATOMIC statement must set a scalar variable of "
   11065            4 :                  "intrinsic type at %L", &stmt->expr1->where);
   11066            4 :       return;
   11067              :     }
   11068              : 
   11069         2687 :   if (!gfc_resolve_expr (stmt->expr2))
   11070              :     return;
   11071         2683 :   if (!is_scalar_intrinsic_expr (stmt->expr2, false, false))
   11072              :     {
   11073            0 :       gfc_error ("!$OMP ATOMIC statement must assign an expression of "
   11074            0 :                  "intrinsic type at %L", &stmt->expr2->where);
   11075            0 :       return;
   11076              :     }
   11077              : 
   11078         2683 :   if (gfc_expr_attr (stmt->expr1).allocatable)
   11079              :     {
   11080            0 :       gfc_error ("!$OMP ATOMIC with ALLOCATABLE variable at %L",
   11081            0 :                  &stmt->expr1->where);
   11082            0 :       return;
   11083              :     }
   11084              : 
   11085              :   /* Should be diagnosed above already. */
   11086         2683 :   gcc_assert (tailing_stmt == NULL);
   11087              : 
   11088         2683 :   var = stmt->expr1->symtree->n.sym;
   11089         2683 :   stmt_expr2 = is_conversion (stmt->expr2, true, true);
   11090         2683 :   if (stmt_expr2 == NULL)
   11091         2527 :     stmt_expr2 = stmt->expr2;
   11092              : 
   11093         2683 :   switch (aop)
   11094              :     {
   11095          503 :     case GFC_OMP_ATOMIC_READ:
   11096          503 :       if (stmt_expr2->expr_type != EXPR_VARIABLE)
   11097            0 :         gfc_error ("!$OMP ATOMIC READ statement must read from a scalar "
   11098              :                    "variable of intrinsic type at %L", &stmt_expr2->where);
   11099              :       return;
   11100          421 :     case GFC_OMP_ATOMIC_WRITE:
   11101          421 :       if (expr_references_sym (stmt_expr2, var, NULL))
   11102            0 :         gfc_error ("expr in !$OMP ATOMIC WRITE assignment var = expr "
   11103              :                    "must be scalar and cannot reference var at %L",
   11104              :                    &stmt_expr2->where);
   11105              :       return;
   11106         1759 :     default:
   11107         1759 :       break;
   11108              :     }
   11109              : 
   11110         1759 :   if (atomic_code->ext.omp_clauses->capture)
   11111              :     {
   11112          588 :       if (!is_scalar_intrinsic_expr (capture_stmt->expr1, true, false))
   11113              :         {
   11114            0 :           gfc_error ("!$OMP ATOMIC capture-statement must set a scalar "
   11115              :                      "variable of intrinsic type at %L",
   11116            0 :                      &capture_stmt->expr1->where);
   11117            0 :           return;
   11118              :         }
   11119              : 
   11120          588 :       if (!is_scalar_intrinsic_expr (capture_stmt->expr2, true, true))
   11121              :         {
   11122            2 :           gfc_error ("!$OMP ATOMIC capture-statement requires a scalar variable"
   11123            2 :                      " of intrinsic type at %L", &capture_stmt->expr2->where);
   11124            2 :           return;
   11125              :         }
   11126          586 :       capt_expr2 = is_conversion (capture_stmt->expr2, true, true);
   11127          586 :       if (capt_expr2 == NULL)
   11128          564 :         capt_expr2 = capture_stmt->expr2;
   11129              : 
   11130          586 :       if (capt_expr2->symtree->n.sym != var)
   11131              :         {
   11132            1 :           gfc_error ("!$OMP ATOMIC CAPTURE capture statement reads from "
   11133              :                      "different variable than update statement writes "
   11134              :                      "into at %L", &capture_stmt->expr2->where);
   11135            1 :               return;
   11136              :         }
   11137              :     }
   11138              : 
   11139         1756 :   if (atomic_code->ext.omp_clauses->compare)
   11140              :     {
   11141          149 :       gfc_expr *var_expr;
   11142          149 :       if (comp_cond->value.op.op1->expr_type == EXPR_VARIABLE)
   11143              :         var_expr = comp_cond->value.op.op1;
   11144              :       else
   11145           12 :         var_expr = comp_cond->value.op.op1->value.function.actual->expr;
   11146          149 :       if (var_expr->symtree->n.sym != var)
   11147              :         {
   11148            2 :           gfc_error ("For !$OMP ATOMIC COMPARE, the first operand in comparison"
   11149              :                      " at %L must be the variable %qs that the update statement"
   11150              :                      " writes into at %L", &var_expr->where, var->name,
   11151            2 :                      &stmt->expr1->where);
   11152            2 :           return;
   11153              :         }
   11154          147 :       if (stmt_expr2->rank != 0 || expr_references_sym (stmt_expr2, var, NULL))
   11155              :         {
   11156            1 :           gfc_error ("expr in !$OMP ATOMIC COMPARE assignment var = expr "
   11157              :                      "must be scalar and cannot reference var at %L",
   11158              :                      &stmt_expr2->where);
   11159            1 :           return;
   11160              :         }
   11161              :     }
   11162         1607 :   else if (atomic_code->ext.omp_clauses->capture
   11163         1607 :            && !expr_references_sym (stmt_expr2, var, NULL))
   11164           22 :     atomic_code->ext.omp_clauses->atomic_op
   11165           22 :       = (gfc_omp_atomic_op) (atomic_code->ext.omp_clauses->atomic_op
   11166              :                              | GFC_OMP_ATOMIC_SWAP);
   11167         1585 :   else if (stmt_expr2->expr_type == EXPR_OP)
   11168              :     {
   11169         1229 :       gfc_expr *v = NULL, *e, *c;
   11170         1229 :       gfc_intrinsic_op op = stmt_expr2->value.op.op;
   11171         1229 :       gfc_intrinsic_op alt_op = INTRINSIC_NONE;
   11172              : 
   11173         1229 :       if (atomic_code->ext.omp_clauses->fail != OMP_MEMORDER_UNSET)
   11174            3 :         gfc_error ("!$OMP ATOMIC UPDATE at %L with FAIL clause requires either"
   11175              :                    " the COMPARE clause or using the intrinsic MIN/MAX "
   11176              :                    "procedure", &atomic_code->loc);
   11177         1229 :       switch (op)
   11178              :         {
   11179          742 :         case INTRINSIC_PLUS:
   11180          742 :           alt_op = INTRINSIC_MINUS;
   11181          742 :           break;
   11182           94 :         case INTRINSIC_TIMES:
   11183           94 :           alt_op = INTRINSIC_DIVIDE;
   11184           94 :           break;
   11185          120 :         case INTRINSIC_MINUS:
   11186          120 :           alt_op = INTRINSIC_PLUS;
   11187          120 :           break;
   11188           94 :         case INTRINSIC_DIVIDE:
   11189           94 :           alt_op = INTRINSIC_TIMES;
   11190           94 :           break;
   11191              :         case INTRINSIC_AND:
   11192              :         case INTRINSIC_OR:
   11193              :           break;
   11194           43 :         case INTRINSIC_EQV:
   11195           43 :           alt_op = INTRINSIC_NEQV;
   11196           43 :           break;
   11197           43 :         case INTRINSIC_NEQV:
   11198           43 :           alt_op = INTRINSIC_EQV;
   11199           43 :           break;
   11200            1 :         default:
   11201            1 :           gfc_error ("!$OMP ATOMIC assignment operator must be binary "
   11202              :                      "+, *, -, /, .AND., .OR., .EQV. or .NEQV. at %L",
   11203              :                      &stmt_expr2->where);
   11204            1 :           return;
   11205              :         }
   11206              : 
   11207              :       /* Check for var = var op expr resp. var = expr op var where
   11208              :          expr doesn't reference var and var op expr is mathematically
   11209              :          equivalent to var op (expr) resp. expr op var equivalent to
   11210              :          (expr) op var.  We rely here on the fact that the matcher
   11211              :          for x op1 y op2 z where op1 and op2 have equal precedence
   11212              :          returns (x op1 y) op2 z.  */
   11213         1228 :       e = stmt_expr2->value.op.op2;
   11214         1228 :       if (e->expr_type == EXPR_VARIABLE
   11215          288 :           && e->symtree != NULL
   11216          288 :           && e->symtree->n.sym == var)
   11217              :         v = e;
   11218          999 :       else if ((c = is_conversion (e, false, true)) != NULL
   11219           48 :                && c->expr_type == EXPR_VARIABLE
   11220           48 :                && c->symtree != NULL
   11221         1047 :                && c->symtree->n.sym == var)
   11222              :         v = c;
   11223              :       else
   11224              :         {
   11225          951 :           gfc_expr **p = NULL, **q;
   11226         1049 :           for (q = &stmt_expr2->value.op.op1; (e = *q) != NULL; )
   11227         1049 :             if (e->expr_type == EXPR_VARIABLE
   11228          948 :                 && e->symtree != NULL
   11229          948 :                 && e->symtree->n.sym == var)
   11230              :               {
   11231              :                 v = e;
   11232              :                 break;
   11233              :               }
   11234          101 :             else if ((c = is_conversion (e, false, true)) != NULL)
   11235           60 :               q = &e->value.function.actual->expr;
   11236           41 :             else if (e->expr_type != EXPR_OP
   11237           41 :                      || (e->value.op.op != op
   11238           15 :                          && e->value.op.op != alt_op)
   11239           38 :                      || e->rank != 0)
   11240              :               break;
   11241              :             else
   11242              :               {
   11243           38 :                 p = q;
   11244           38 :                 q = &e->value.op.op1;
   11245              :               }
   11246              : 
   11247          951 :           if (v == NULL)
   11248              :             {
   11249            3 :               gfc_error ("!$OMP ATOMIC assignment must be var = var op expr "
   11250              :                          "or var = expr op var at %L", &stmt_expr2->where);
   11251            3 :               return;
   11252              :             }
   11253              : 
   11254          948 :           if (p != NULL)
   11255              :             {
   11256           38 :               e = *p;
   11257           38 :               switch (e->value.op.op)
   11258              :                 {
   11259            8 :                 case INTRINSIC_MINUS:
   11260            8 :                 case INTRINSIC_DIVIDE:
   11261            8 :                 case INTRINSIC_EQV:
   11262            8 :                 case INTRINSIC_NEQV:
   11263            8 :                   gfc_error ("!$OMP ATOMIC var = var op expr not "
   11264              :                              "mathematically equivalent to var = var op "
   11265              :                              "(expr) at %L", &stmt_expr2->where);
   11266            8 :                   break;
   11267              :                 default:
   11268              :                   break;
   11269              :                 }
   11270              : 
   11271              :               /* Canonicalize into var = var op (expr).  */
   11272           38 :               *p = e->value.op.op2;
   11273           38 :               e->value.op.op2 = stmt_expr2;
   11274           38 :               e->ts = stmt_expr2->ts;
   11275           38 :               if (stmt->expr2 == stmt_expr2)
   11276           26 :                 stmt->expr2 = stmt_expr2 = e;
   11277              :               else
   11278           12 :                 stmt->expr2->value.function.actual->expr = stmt_expr2 = e;
   11279              : 
   11280           38 :               if (!gfc_compare_types (&stmt_expr2->value.op.op1->ts,
   11281              :                                       &stmt_expr2->ts))
   11282              :                 {
   11283           24 :                   for (p = &stmt_expr2->value.op.op1; *p != v;
   11284           12 :                        p = &(*p)->value.function.actual->expr)
   11285              :                     ;
   11286           12 :                   *p = NULL;
   11287           12 :                   gfc_free_expr (stmt_expr2->value.op.op1);
   11288           12 :                   stmt_expr2->value.op.op1 = v;
   11289           12 :                   gfc_convert_type (v, &stmt_expr2->ts, 2);
   11290              :                 }
   11291              :             }
   11292              :         }
   11293              : 
   11294         1225 :       if (e->rank != 0 || expr_references_sym (stmt->expr2, var, v))
   11295              :         {
   11296            1 :           gfc_error ("expr in !$OMP ATOMIC assignment var = var op expr "
   11297              :                      "must be scalar and cannot reference var at %L",
   11298              :                      &stmt_expr2->where);
   11299            1 :           return;
   11300              :         }
   11301              :     }
   11302          356 :   else if (stmt_expr2->expr_type == EXPR_FUNCTION
   11303          355 :            && stmt_expr2->value.function.isym != NULL
   11304          355 :            && stmt_expr2->value.function.esym == NULL
   11305          355 :            && stmt_expr2->value.function.actual != NULL
   11306          355 :            && stmt_expr2->value.function.actual->next != NULL)
   11307              :     {
   11308          355 :       gfc_actual_arglist *arg, *var_arg;
   11309              : 
   11310          355 :       switch (stmt_expr2->value.function.isym->id)
   11311              :         {
   11312              :         case GFC_ISYM_MIN:
   11313              :         case GFC_ISYM_MAX:
   11314              :           break;
   11315          147 :         case GFC_ISYM_IAND:
   11316          147 :         case GFC_ISYM_IOR:
   11317          147 :         case GFC_ISYM_IEOR:
   11318          147 :           if (stmt_expr2->value.function.actual->next->next != NULL)
   11319              :             {
   11320            0 :               gfc_error ("!$OMP ATOMIC assignment intrinsic IAND, IOR "
   11321              :                          "or IEOR must have two arguments at %L",
   11322              :                          &stmt_expr2->where);
   11323            0 :               return;
   11324              :             }
   11325              :           break;
   11326            1 :         default:
   11327            1 :           gfc_error ("!$OMP ATOMIC assignment intrinsic must be "
   11328              :                      "MIN, MAX, IAND, IOR or IEOR at %L",
   11329              :                      &stmt_expr2->where);
   11330            1 :           return;
   11331              :         }
   11332              : 
   11333              :       var_arg = NULL;
   11334         1088 :       for (arg = stmt_expr2->value.function.actual; arg; arg = arg->next)
   11335              :         {
   11336          741 :           gfc_expr *e = NULL;
   11337          741 :           if (arg == stmt_expr2->value.function.actual
   11338          387 :               || (var_arg == NULL && arg->next == NULL))
   11339              :             {
   11340          527 :               e = is_conversion (arg->expr, false, true);
   11341          527 :               if (!e)
   11342          514 :                 e = arg->expr;
   11343          527 :               if (e->expr_type == EXPR_VARIABLE
   11344          453 :                   && e->symtree != NULL
   11345          453 :                   && e->symtree->n.sym == var)
   11346          741 :                 var_arg = arg;
   11347              :             }
   11348          741 :           if ((!var_arg || !e) && expr_references_sym (arg->expr, var, NULL))
   11349              :             {
   11350            7 :               gfc_error ("!$OMP ATOMIC intrinsic arguments except one must "
   11351              :                          "not reference %qs at %L",
   11352              :                          var->name, &arg->expr->where);
   11353            7 :               return;
   11354              :             }
   11355          734 :           if (arg->expr->rank != 0)
   11356              :             {
   11357            0 :               gfc_error ("!$OMP ATOMIC intrinsic arguments must be scalar "
   11358              :                          "at %L", &arg->expr->where);
   11359            0 :               return;
   11360              :             }
   11361              :         }
   11362              : 
   11363          347 :       if (var_arg == NULL)
   11364              :         {
   11365            1 :           gfc_error ("First or last !$OMP ATOMIC intrinsic argument must "
   11366              :                      "be %qs at %L", var->name, &stmt_expr2->where);
   11367            1 :           return;
   11368              :         }
   11369              : 
   11370          346 :       if (var_arg != stmt_expr2->value.function.actual)
   11371              :         {
   11372              :           /* Canonicalize, so that var comes first.  */
   11373          172 :           gcc_assert (var_arg->next == NULL);
   11374              :           for (arg = stmt_expr2->value.function.actual;
   11375          185 :                arg->next != var_arg; arg = arg->next)
   11376              :             ;
   11377          172 :           var_arg->next = stmt_expr2->value.function.actual;
   11378          172 :           stmt_expr2->value.function.actual = var_arg;
   11379          172 :           arg->next = NULL;
   11380              :         }
   11381              :     }
   11382              :   else
   11383            1 :     gfc_error ("!$OMP ATOMIC assignment must have an operator or "
   11384              :                "intrinsic on right hand side at %L", &stmt_expr2->where);
   11385              :   return;
   11386              : 
   11387            4 : unexpected:
   11388            4 :   gfc_error ("unexpected !$OMP ATOMIC expression at %L",
   11389              :              loc ? loc : &code->loc);
   11390            4 :   return;
   11391              : }
   11392              : 
   11393              : 
   11394              : static struct fortran_omp_context
   11395              : {
   11396              :   gfc_code *code;
   11397              :   hash_set<gfc_symbol *> *sharing_clauses;
   11398              :   hash_set<gfc_symbol *> *private_iterators;
   11399              :   struct fortran_omp_context *previous;
   11400              :   bool is_openmp;
   11401              : } *omp_current_ctx;
   11402              : static gfc_code *omp_current_do_code;
   11403              : static int omp_current_do_collapse;
   11404              : 
   11405              : /* Forward declaration for mutually recursive functions.  */
   11406              : static gfc_code *
   11407              : find_nested_loop_in_block (gfc_code *block);
   11408              : 
   11409              : /* Return the first nested DO loop in CHAIN, or NULL if there
   11410              :    isn't one.  Does no error checking on intervening code.  */
   11411              : 
   11412              : static gfc_code *
   11413        27476 : find_nested_loop_in_chain (gfc_code *chain)
   11414              : {
   11415        27476 :   gfc_code *code;
   11416              : 
   11417        27476 :   if (!chain)
   11418              :     return NULL;
   11419              : 
   11420        31637 :   for (code = chain; code; code = code->next)
   11421        31216 :     switch (code->op)
   11422              :       {
   11423              :       case EXEC_DO:
   11424              :       case EXEC_OMP_TILE:
   11425              :       case EXEC_OMP_UNROLL:
   11426              :         return code;
   11427          621 :       case EXEC_BLOCK:
   11428          621 :         if (gfc_code *c = find_nested_loop_in_block (code))
   11429              :           return c;
   11430              :         break;
   11431              :       default:
   11432              :         break;
   11433              :       }
   11434              :   return NULL;
   11435              : }
   11436              : 
   11437              : /* Return the first nested DO loop in BLOCK, or NULL if there
   11438              :    isn't one.  Does no error checking on intervening code.  */
   11439              : static gfc_code *
   11440          939 : find_nested_loop_in_block (gfc_code *block)
   11441              : {
   11442          939 :   gfc_namespace *ns;
   11443          939 :   gcc_assert (block->op == EXEC_BLOCK);
   11444          939 :   ns = block->ext.block.ns;
   11445          939 :   gcc_assert (ns);
   11446          939 :   return find_nested_loop_in_chain (ns->code);
   11447              : }
   11448              : 
   11449              : void
   11450         5412 : gfc_resolve_omp_do_blocks (gfc_code *code, gfc_namespace *ns)
   11451              : {
   11452         5412 :   if (code->block->next && code->block->next->op == EXEC_DO)
   11453              :     {
   11454         5059 :       int i;
   11455              : 
   11456         5059 :       omp_current_do_code = code->block->next;
   11457         5059 :       if (code->ext.omp_clauses->orderedc)
   11458          142 :         omp_current_do_collapse = code->ext.omp_clauses->orderedc;
   11459         4917 :       else if (code->ext.omp_clauses->collapse)
   11460         1120 :         omp_current_do_collapse = code->ext.omp_clauses->collapse;
   11461         3797 :       else if (code->ext.omp_clauses->sizes_list)
   11462          175 :         omp_current_do_collapse
   11463          175 :           = gfc_expr_list_len (code->ext.omp_clauses->sizes_list);
   11464              :       else
   11465         3622 :         omp_current_do_collapse = 1;
   11466         5059 :       if (code->ext.omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN])
   11467              :         {
   11468              :           /* Checking that there is a matching EXEC_OMP_SCAN in the
   11469              :              innermost body cannot be deferred to resolve_omp_do because
   11470              :              we process directives nested in the loop before we get
   11471              :              there.  */
   11472           60 :           locus *loc
   11473              :             = &code->ext.omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN]->where;
   11474           60 :           gfc_code *c;
   11475              : 
   11476           80 :           for (i = 1, c = omp_current_do_code;
   11477           80 :                i < omp_current_do_collapse; i++)
   11478              :             {
   11479           22 :               c = find_nested_loop_in_chain (c->block->next);
   11480           22 :               if (!c || c->op != EXEC_DO || c->block == NULL)
   11481              :                 break;
   11482              :             }
   11483              : 
   11484              :           /* Skip this if we don't have enough nested loops.  That
   11485              :              problem will be diagnosed elsewhere.  */
   11486           60 :           if (c && c->op == EXEC_DO)
   11487              :             {
   11488           58 :               gfc_code *block = c->block ? c->block->next : NULL;
   11489           58 :               if (block && block->op != EXEC_OMP_SCAN)
   11490           54 :                 while (block && block->next
   11491           54 :                        && block->next->op != EXEC_OMP_SCAN)
   11492              :                   block = block->next;
   11493           43 :               if (!block
   11494           46 :                   || (block->op != EXEC_OMP_SCAN
   11495           43 :                       && (!block->next || block->next->op != EXEC_OMP_SCAN)))
   11496           19 :                 gfc_error ("With INSCAN at %L, expected loop body with "
   11497              :                            "!$OMP SCAN between two "
   11498              :                            "structured block sequences", loc);
   11499              :               else
   11500              :                 {
   11501           39 :                   if (block->op == EXEC_OMP_SCAN)
   11502            3 :                     gfc_warning (OPT_Wopenmp,
   11503              :                                  "!$OMP SCAN at %L with zero executable "
   11504              :                                  "statements in preceding structured block "
   11505              :                                  "sequence", &block->loc);
   11506           39 :                   if ((block->op == EXEC_OMP_SCAN && !block->next)
   11507           38 :                       || (block->next && block->next->op == EXEC_OMP_SCAN
   11508           36 :                           && !block->next->next))
   11509            3 :                     gfc_warning (OPT_Wopenmp,
   11510              :                                  "!$OMP SCAN at %L with zero executable "
   11511              :                                  "statements in succeeding structured block "
   11512              :                                  "sequence", block->op == EXEC_OMP_SCAN
   11513            1 :                                  ? &block->loc : &block->next->loc);
   11514              :                 }
   11515           58 :               if (block && block->op != EXEC_OMP_SCAN)
   11516           43 :                 block = block->next;
   11517           46 :               if (block && block->op == EXEC_OMP_SCAN)
   11518              :                 /* Mark 'omp scan' as checked; flag will be unset later.  */
   11519           39 :                 block->ext.omp_clauses->if_present = true;
   11520              :             }
   11521              :         }
   11522              :     }
   11523         5412 :   gfc_resolve_blocks (code->block, ns);
   11524         5412 :   omp_current_do_collapse = 0;
   11525         5412 :   omp_current_do_code = NULL;
   11526         5412 : }
   11527              : 
   11528              : 
   11529              : void
   11530         6014 : gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
   11531              : {
   11532         6014 :   struct fortran_omp_context ctx;
   11533         6014 :   gfc_omp_clauses *omp_clauses = code->ext.omp_clauses;
   11534         6014 :   gfc_omp_namelist *n;
   11535         6014 :   int list;
   11536              : 
   11537         6014 :   ctx.code = code;
   11538         6014 :   ctx.sharing_clauses = new hash_set<gfc_symbol *>;
   11539         6014 :   ctx.private_iterators = new hash_set<gfc_symbol *>;
   11540         6014 :   ctx.previous = omp_current_ctx;
   11541         6014 :   ctx.is_openmp = true;
   11542         6014 :   omp_current_ctx = &ctx;
   11543              : 
   11544       240560 :   for (list = 0; list < OMP_LIST_NUM; list++)
   11545       234546 :     switch (list)
   11546              :       {
   11547        60140 :       case OMP_LIST_SHARED:
   11548        60140 :       case OMP_LIST_PRIVATE:
   11549        60140 :       case OMP_LIST_FIRSTPRIVATE:
   11550        60140 :       case OMP_LIST_LASTPRIVATE:
   11551        60140 :       case OMP_LIST_REDUCTION:
   11552        60140 :       case OMP_LIST_REDUCTION_INSCAN:
   11553        60140 :       case OMP_LIST_REDUCTION_TASK:
   11554        60140 :       case OMP_LIST_IN_REDUCTION:
   11555        60140 :       case OMP_LIST_TASK_REDUCTION:
   11556        60140 :       case OMP_LIST_LINEAR:
   11557        69059 :         for (n = omp_clauses->lists[list]; n; n = n->next)
   11558         8919 :           ctx.sharing_clauses->add (n->sym);
   11559              :         break;
   11560              :       default:
   11561              :         break;
   11562              :       }
   11563              : 
   11564         6014 :   switch (code->op)
   11565              :     {
   11566         2349 :     case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
   11567         2349 :     case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
   11568         2349 :     case EXEC_OMP_MASKED_TASKLOOP:
   11569         2349 :     case EXEC_OMP_MASKED_TASKLOOP_SIMD:
   11570         2349 :     case EXEC_OMP_MASTER_TASKLOOP:
   11571         2349 :     case EXEC_OMP_MASTER_TASKLOOP_SIMD:
   11572         2349 :     case EXEC_OMP_PARALLEL_DO:
   11573         2349 :     case EXEC_OMP_PARALLEL_DO_SIMD:
   11574         2349 :     case EXEC_OMP_PARALLEL_LOOP:
   11575         2349 :     case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
   11576         2349 :     case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
   11577         2349 :     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
   11578         2349 :     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
   11579         2349 :     case EXEC_OMP_TARGET_PARALLEL_DO:
   11580         2349 :     case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
   11581         2349 :     case EXEC_OMP_TARGET_PARALLEL_LOOP:
   11582         2349 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
   11583         2349 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
   11584         2349 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
   11585         2349 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
   11586         2349 :     case EXEC_OMP_TARGET_TEAMS_LOOP:
   11587         2349 :     case EXEC_OMP_TASKLOOP:
   11588         2349 :     case EXEC_OMP_TASKLOOP_SIMD:
   11589         2349 :     case EXEC_OMP_TEAMS_DISTRIBUTE:
   11590         2349 :     case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
   11591         2349 :     case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
   11592         2349 :     case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
   11593         2349 :     case EXEC_OMP_TEAMS_LOOP:
   11594         2349 :       gfc_resolve_omp_do_blocks (code, ns);
   11595         2349 :       break;
   11596         3665 :     default:
   11597         3665 :       gfc_resolve_blocks (code->block, ns);
   11598              :     }
   11599              : 
   11600         6014 :   omp_current_ctx = ctx.previous;
   11601        12028 :   delete ctx.sharing_clauses;
   11602        12028 :   delete ctx.private_iterators;
   11603         6014 : }
   11604              : 
   11605              : 
   11606              : /* Save and clear openmp.cc private state.  */
   11607              : 
   11608              : void
   11609       284919 : gfc_omp_save_and_clear_state (struct gfc_omp_saved_state *state)
   11610              : {
   11611       284919 :   state->ptrs[0] = omp_current_ctx;
   11612       284919 :   state->ptrs[1] = omp_current_do_code;
   11613       284919 :   state->ints[0] = omp_current_do_collapse;
   11614       284919 :   omp_current_ctx = NULL;
   11615       284919 :   omp_current_do_code = NULL;
   11616       284919 :   omp_current_do_collapse = 0;
   11617       284919 : }
   11618              : 
   11619              : 
   11620              : /* Restore openmp.cc private state from the saved state.  */
   11621              : 
   11622              : void
   11623       284918 : gfc_omp_restore_state (struct gfc_omp_saved_state *state)
   11624              : {
   11625       284918 :   omp_current_ctx = (struct fortran_omp_context *) state->ptrs[0];
   11626       284918 :   omp_current_do_code = (gfc_code *) state->ptrs[1];
   11627       284918 :   omp_current_do_collapse = state->ints[0];
   11628       284918 : }
   11629              : 
   11630              : 
   11631              : /* Note a DO iterator variable.  This is special in !$omp parallel
   11632              :    construct, where they are predetermined private.  */
   11633              : 
   11634              : void
   11635        32789 : gfc_resolve_do_iterator (gfc_code *code, gfc_symbol *sym, bool add_clause)
   11636              : {
   11637        32789 :   if (omp_current_ctx == NULL)
   11638              :     return;
   11639              : 
   11640        13083 :   int i = omp_current_do_collapse;
   11641        13083 :   gfc_code *c = omp_current_do_code;
   11642              : 
   11643        13083 :   if (sym->attr.threadprivate)
   11644              :     return;
   11645              : 
   11646              :   /* !$omp do and !$omp parallel do iteration variable is predetermined
   11647              :      private just in the !$omp do resp. !$omp parallel do construct,
   11648              :      with no implications for the outer parallel constructs.  */
   11649              : 
   11650        17917 :   while (i-- >= 1 && c)
   11651              :     {
   11652         9480 :       if (code == c)
   11653              :         return;
   11654         4834 :       c = find_nested_loop_in_chain (c->block->next);
   11655         4834 :       if (c && (c->op == EXEC_OMP_TILE || c->op == EXEC_OMP_UNROLL))
   11656              :         return;
   11657              :     }
   11658              : 
   11659              :   /* An openacc context may represent a data clause.  Abort if so.  */
   11660         8437 :   if (!omp_current_ctx->is_openmp && !oacc_is_loop (omp_current_ctx->code))
   11661              :     return;
   11662              : 
   11663         7459 :   if (omp_current_ctx->sharing_clauses->contains (sym))
   11664              :     return;
   11665              : 
   11666         6457 :   if (! omp_current_ctx->private_iterators->add (sym) && add_clause)
   11667              :     {
   11668         6270 :       gfc_omp_clauses *omp_clauses = omp_current_ctx->code->ext.omp_clauses;
   11669         6270 :       gfc_omp_namelist *p;
   11670              : 
   11671         6270 :       p = gfc_get_omp_namelist ();
   11672         6270 :       p->sym = sym;
   11673         6270 :       p->where = omp_current_ctx->code->loc;
   11674         6270 :       p->next = omp_clauses->lists[OMP_LIST_PRIVATE];
   11675         6270 :       omp_clauses->lists[OMP_LIST_PRIVATE] = p;
   11676              :     }
   11677              : }
   11678              : 
   11679              : static void
   11680          698 : handle_local_var (gfc_symbol *sym)
   11681              : {
   11682          698 :   if (sym->attr.flavor != FL_VARIABLE
   11683          178 :       || sym->as != NULL
   11684          137 :       || (sym->ts.type != BT_INTEGER && sym->ts.type != BT_REAL))
   11685              :     return;
   11686           71 :   gfc_resolve_do_iterator (sym->ns->code, sym, false);
   11687              : }
   11688              : 
   11689              : void
   11690       330629 : gfc_resolve_omp_local_vars (gfc_namespace *ns)
   11691              : {
   11692       330629 :   if (omp_current_ctx)
   11693          452 :     gfc_traverse_ns (ns, handle_local_var);
   11694       330629 : }
   11695              : 
   11696              : 
   11697              : /* Error checking on intervening code uses a code walker.  */
   11698              : 
   11699              : struct icode_error_state
   11700              : {
   11701              :   const char *name;
   11702              :   bool errorp;
   11703              :   gfc_code *nested;
   11704              :   gfc_code *next;
   11705              : };
   11706              : 
   11707              : static int
   11708          944 : icode_code_error_callback (gfc_code **codep,
   11709              :                            int *walk_subtrees ATTRIBUTE_UNUSED, void *opaque)
   11710              : {
   11711          944 :   gfc_code *code = *codep;
   11712          944 :   icode_error_state *state = (icode_error_state *)opaque;
   11713              : 
   11714              :   /* gfc_code_walker walks down CODE's next chain as well as
   11715              :      walking things that are actually nested in CODE.  We need to
   11716              :      special-case traversal of outer blocks, so stop immediately if we
   11717              :      are heading down such a next chain.  */
   11718          944 :   if (code == state->next)
   11719              :     return 1;
   11720              : 
   11721          647 :   switch (code->op)
   11722              :     {
   11723            1 :     case EXEC_DO:
   11724            1 :     case EXEC_DO_WHILE:
   11725            1 :     case EXEC_DO_CONCURRENT:
   11726            1 :       gfc_error ("%s cannot contain loop in intervening code at %L",
   11727              :                  state->name, &code->loc);
   11728            1 :       state->errorp = true;
   11729            1 :       break;
   11730            0 :     case EXEC_CYCLE:
   11731            0 :     case EXEC_EXIT:
   11732              :       /* Errors have already been diagnosed in match_exit_cycle.  */
   11733            0 :       state->errorp = true;
   11734            0 :       break;
   11735              :     case EXEC_OMP_ASSUME:
   11736              :     case EXEC_OMP_METADIRECTIVE:
   11737              :       /* Per OpenMP 6.0, some non-executable directives are allowed in
   11738              :          intervening code.  */
   11739              :       break;
   11740          477 :     case EXEC_CALL:
   11741              :       /* Per OpenMP 5.2, the "omp_" prefix is reserved, so we don't have to
   11742              :          consider the possibility that some locally-bound definition
   11743              :          overrides the runtime routine.  */
   11744          477 :       if (code->resolved_sym
   11745          477 :           && omp_runtime_api_procname (code->resolved_sym->name))
   11746              :         {
   11747            1 :           gfc_error ("%s cannot contain OpenMP API call in intervening code "
   11748              :                      "at %L",
   11749              :                  state->name, &code->loc);
   11750            1 :           state->errorp = true;
   11751              :         }
   11752              :       break;
   11753          168 :     default:
   11754          168 :       if (code->op >= EXEC_OMP_FIRST_OPENMP_EXEC
   11755          168 :           && code->op <= EXEC_OMP_LAST_OPENMP_EXEC)
   11756              :         {
   11757            2 :           gfc_error ("%s cannot contain OpenMP directive in intervening code "
   11758              :                      "at %L",
   11759              :                      state->name, &code->loc);
   11760            2 :           state->errorp = true;
   11761              :         }
   11762              :     }
   11763              :   return 0;
   11764              : }
   11765              : 
   11766              : static int
   11767         1081 : icode_expr_error_callback (gfc_expr **expr,
   11768              :                            int *walk_subtrees ATTRIBUTE_UNUSED, void *opaque)
   11769              : {
   11770         1081 :   icode_error_state *state = (icode_error_state *)opaque;
   11771              : 
   11772         1081 :   switch ((*expr)->expr_type)
   11773              :     {
   11774              :       /* As for EXPR_CALL with "omp_"-prefixed symbols.  */
   11775            2 :     case EXPR_FUNCTION:
   11776            2 :       {
   11777            2 :         gfc_symbol *sym = (*expr)->value.function.esym;
   11778            2 :         if (sym && omp_runtime_api_procname (sym->name))
   11779              :           {
   11780            1 :             gfc_error ("%s cannot contain OpenMP API call in intervening code "
   11781              :                        "at %L",
   11782            1 :                        state->name, &((*expr)->where));
   11783            1 :             state->errorp = true;
   11784              :           }
   11785              :         }
   11786              : 
   11787              :       break;
   11788              :     default:
   11789              :       break;
   11790              :     }
   11791              : 
   11792              :   /* FIXME: The description of canonical loop form in the OpenMP standard
   11793              :      also says "array expressions" are not permitted in intervening code.
   11794              :      That term is not defined in either the OpenMP spec or the Fortran
   11795              :      standard, although the latter uses it informally to refer to any
   11796              :      expression that is not scalar-valued.  It is also apparently not the
   11797              :      thing GCC internally calls EXPR_ARRAY.  It seems the intent of the
   11798              :      OpenMP restriction is to disallow elemental operations/intrinsics
   11799              :      (including things that are not expressions, like assignment
   11800              :      statements) that generate implicit loops over array operands
   11801              :      (even if the result is a scalar), but even if the spec said
   11802              :      that there is no list of all the cases that would be forbidden.
   11803              :      This is OpenMP issue 3326.  */
   11804              : 
   11805         1081 :   return 0;
   11806              : }
   11807              : 
   11808              : static void
   11809          267 : diagnose_intervening_code_errors_1 (gfc_code *chain,
   11810              :                                     struct icode_error_state *state)
   11811              : {
   11812          267 :   gfc_code *code;
   11813         1080 :   for (code = chain; code; code = code->next)
   11814              :     {
   11815          813 :       if (code == state->nested)
   11816              :         /* Do not walk the nested loop or its body, we are only
   11817              :            interested in intervening code.  */
   11818              :         ;
   11819          636 :       else if (code->op == EXEC_BLOCK
   11820          636 :                && find_nested_loop_in_block (code) == state->nested)
   11821              :         /* This block contains the nested loop, recurse on its
   11822              :            statements.  */
   11823              :         {
   11824           90 :           gfc_namespace* ns = code->ext.block.ns;
   11825           90 :           diagnose_intervening_code_errors_1 (ns->code, state);
   11826              :         }
   11827              :       else
   11828              :         /* Treat the whole statement as a unit.  */
   11829              :         {
   11830          546 :           gfc_code *temp = state->next;
   11831          546 :           state->next = code->next;
   11832          546 :           gfc_code_walker (&code, icode_code_error_callback,
   11833              :                            icode_expr_error_callback, state);
   11834          546 :           state->next = temp;
   11835              :         }
   11836              :     }
   11837          267 : }
   11838              : 
   11839              : /* Diagnose intervening code errors in BLOCK with nested loop NESTED.
   11840              :    NAME is the user-friendly name of the OMP directive, used for error
   11841              :    messages.  Returns true if any error was found.  */
   11842              : static bool
   11843          177 : diagnose_intervening_code_errors (gfc_code *chain, const char *name,
   11844              :                                   gfc_code *nested)
   11845              : {
   11846          177 :   struct icode_error_state state;
   11847          177 :   state.name = name;
   11848          177 :   state.errorp = false;
   11849          177 :   state.nested = nested;
   11850          177 :   state.next = NULL;
   11851            0 :   diagnose_intervening_code_errors_1 (chain, &state);
   11852          177 :   return state.errorp;
   11853              : }
   11854              : 
   11855              : /* Helper function for restructure_intervening_code:  wrap CHAIN in
   11856              :    a marker to indicate that it is a structured block sequence.  That
   11857              :    information will be used later on (in omp-low.cc) for error checking.  */
   11858              : static gfc_code *
   11859          461 : make_structured_block (gfc_code *chain)
   11860              : {
   11861          461 :   gcc_assert (chain);
   11862          461 :   gfc_namespace *ns = gfc_build_block_ns (gfc_current_ns);
   11863          461 :   gfc_code *result = gfc_get_code (EXEC_BLOCK);
   11864          461 :   result->op = EXEC_BLOCK;
   11865          461 :   result->ext.block.ns = ns;
   11866          461 :   result->ext.block.assoc = NULL;
   11867          461 :   result->loc = chain->loc;
   11868          461 :   ns->omp_structured_block = 1;
   11869          461 :   ns->code = chain;
   11870          461 :   return result;
   11871              : }
   11872              : 
   11873              : /* Push intervening code surrounding a loop, including nested scopes,
   11874              :    into the body of the loop.  CHAINP is the pointer to the head of
   11875              :    the next-chain to scan, OUTER_LOOP is the EXEC_DO for the next outer
   11876              :    loop level, and COLLAPSE is the number of nested loops we need to
   11877              :    process.
   11878              :    Note that CHAINP may point at outer_loop->block->next when we
   11879              :    are scanning the body of a loop, but if there is an intervening block
   11880              :    CHAINP points into the block's chain rather than its enclosing outer
   11881              :    loop.  This is why OUTER_LOOP is passed separately.  */
   11882              : static gfc_code *
   11883         7161 : restructure_intervening_code (gfc_code **chainp, gfc_code *outer_loop,
   11884              :                               int count)
   11885              : {
   11886         7161 :   gfc_code *code;
   11887         7161 :   gfc_code *head = *chainp;
   11888         7161 :   gfc_code *tail = NULL;
   11889         7161 :   gfc_code *innermost_loop = NULL;
   11890              : 
   11891         7425 :   for (code = *chainp; code; code = code->next, chainp = &(*chainp)->next)
   11892              :     {
   11893         7425 :       if (code->op == EXEC_DO)
   11894              :         {
   11895              :           /* Cut CODE free from its chain, leaving the ends dangling.  */
   11896         7077 :           *chainp = NULL;
   11897         7077 :           tail = code->next;
   11898         7077 :           code->next = NULL;
   11899              : 
   11900         7077 :           if (count == 1)
   11901              :             innermost_loop = code;
   11902              :           else
   11903         2089 :             innermost_loop
   11904         2089 :               = restructure_intervening_code (&code->block->next,
   11905              :                                               code, count - 1);
   11906              :           break;
   11907              :         }
   11908          348 :       else if (code->op == EXEC_BLOCK
   11909          348 :                && find_nested_loop_in_block (code))
   11910              :         {
   11911           84 :           gfc_namespace *ns = code->ext.block.ns;
   11912              : 
   11913              :           /* Cut CODE free from its chain, leaving the ends dangling.  */
   11914           84 :           *chainp = NULL;
   11915           84 :           tail = code->next;
   11916           84 :           code->next = NULL;
   11917              : 
   11918           84 :           innermost_loop
   11919           84 :             = restructure_intervening_code (&ns->code, outer_loop,
   11920              :                                             count);
   11921              : 
   11922              :           /* At this point we have already pulled out the nested loop and
   11923              :              pointed outer_loop at it, and moved the intervening code that
   11924              :              was previously in the block into the body of innermost_loop.
   11925              :              Now we want to move the BLOCK itself so it wraps the entire
   11926              :              current body of innermost_loop.  */
   11927           84 :           ns->code = innermost_loop->block->next;
   11928           84 :           innermost_loop->block->next = code;
   11929           84 :           break;
   11930              :         }
   11931              :     }
   11932              : 
   11933         2173 :   gcc_assert (innermost_loop);
   11934              : 
   11935              :   /* Now we have split the intervening code into two parts:
   11936              :      head is the start of the part before the loop/block, terminating
   11937              :      at *chainp, and tail is the part after it.  Mark each part as
   11938              :      a structured block sequence, and splice the two parts around the
   11939              :      existing body of the innermost loop.  */
   11940         7161 :   if (head != code)
   11941              :     {
   11942          222 :       gfc_code *block = make_structured_block (head);
   11943          222 :       if (innermost_loop->block->next)
   11944          221 :         gfc_append_code (block, innermost_loop->block->next);
   11945          222 :       innermost_loop->block->next = block;
   11946              :     }
   11947         7161 :   if (tail)
   11948              :     {
   11949          239 :       gfc_code *block = make_structured_block (tail);
   11950          239 :       if (innermost_loop->block->next)
   11951          237 :         gfc_append_code (innermost_loop->block->next, block);
   11952              :       else
   11953            2 :         innermost_loop->block->next = block;
   11954              :     }
   11955              : 
   11956              :   /* For loops, finally splice CODE into OUTER_LOOP.  We already handled
   11957              :      relinking EXEC_BLOCK above.  */
   11958         7161 :   if (code->op == EXEC_DO && outer_loop)
   11959         7077 :     outer_loop->block->next = code;
   11960              : 
   11961         7161 :   return innermost_loop;
   11962              : }
   11963              : 
   11964              : /* CODE is an OMP loop construct.  Return true if VAR matches an iteration
   11965              :    variable outer to level DEPTH.  */
   11966              : static bool
   11967         8074 : is_outer_iteration_variable (gfc_code *code, int depth, gfc_symbol *var)
   11968              : {
   11969         8074 :   int i;
   11970         8074 :   gfc_code *do_code = code;
   11971              : 
   11972        12600 :   for (i = 1; i < depth; i++)
   11973              :     {
   11974         5027 :       do_code = find_nested_loop_in_chain (do_code->block->next);
   11975         5027 :       gcc_assert (do_code);
   11976         5027 :       if (do_code->op == EXEC_OMP_TILE || do_code->op == EXEC_OMP_UNROLL)
   11977              :         {
   11978           51 :           --i;
   11979           51 :           continue;
   11980              :         }
   11981         4976 :       gfc_symbol *ivar = do_code->ext.iterator->var->symtree->n.sym;
   11982         4976 :       if (var == ivar)
   11983              :         return true;
   11984              :     }
   11985              :   return false;
   11986              : }
   11987              : 
   11988              : /* Forward declaration for recursive functions.  */
   11989              : static gfc_code *
   11990              : check_nested_loop_in_block (gfc_code *block, gfc_expr *expr, gfc_symbol *sym,
   11991              :                             bool *bad);
   11992              : 
   11993              : /* Like find_nested_loop_in_chain, but additionally check that EXPR
   11994              :    does not reference any variables bound in intervening EXEC_BLOCKs
   11995              :    and that SYM is not bound in such intervening blocks.  Either EXPR or SYM
   11996              :    may be null.  Sets *BAD to true if either test fails.  */
   11997              : static gfc_code *
   11998        48125 : check_nested_loop_in_chain (gfc_code *chain, gfc_expr *expr, gfc_symbol *sym,
   11999              :                             bool *bad)
   12000              : {
   12001        51729 :   for (gfc_code *code = chain; code; code = code->next)
   12002              :     {
   12003        51441 :       if (code->op == EXEC_DO)
   12004              :         return code;
   12005         4123 :       else if (code->op == EXEC_OMP_TILE || code->op == EXEC_OMP_UNROLL)
   12006         1682 :         return check_nested_loop_in_chain (code->block->next, expr, sym, bad);
   12007         2441 :       else if (code->op == EXEC_BLOCK)
   12008              :         {
   12009          807 :           gfc_code *c = check_nested_loop_in_block (code, expr, sym, bad);
   12010          807 :           if (c)
   12011              :             return c;
   12012              :         }
   12013              :     }
   12014              :   return NULL;
   12015              : }
   12016              : 
   12017              : /* Code walker for block symtrees.  It doesn't take any kind of state
   12018              :    argument, so use a static variable.  */
   12019              : static struct check_nested_loop_in_block_state_t {
   12020              :   gfc_expr *expr;
   12021              :   gfc_symbol *sym;
   12022              :   bool *bad;
   12023              : } check_nested_loop_in_block_state;
   12024              : 
   12025              : static void
   12026          766 : check_nested_loop_in_block_symbol (gfc_symbol *sym)
   12027              : {
   12028          766 :   if (sym == check_nested_loop_in_block_state.sym
   12029          766 :       || (check_nested_loop_in_block_state.expr
   12030          567 :           && gfc_find_sym_in_expr (sym,
   12031              :                                    check_nested_loop_in_block_state.expr)))
   12032            5 :     *check_nested_loop_in_block_state.bad = true;
   12033          766 : }
   12034              : 
   12035              : /* Return the first nested DO loop in BLOCK, or NULL if there
   12036              :    isn't one.  Set *BAD to true if EXPR references any variables in BLOCK, or
   12037              :    SYM is bound in BLOCK.  Either EXPR or SYM may be null.  */
   12038              : static gfc_code *
   12039          807 : check_nested_loop_in_block (gfc_code *block, gfc_expr *expr,
   12040              :                             gfc_symbol *sym, bool *bad)
   12041              : {
   12042          807 :   gfc_namespace *ns;
   12043          807 :   gcc_assert (block->op == EXEC_BLOCK);
   12044          807 :   ns = block->ext.block.ns;
   12045          807 :   gcc_assert (ns);
   12046              : 
   12047              :   /* Skip the check if this block doesn't contain the nested loop, or
   12048              :      if we already know it's bad.  */
   12049          807 :   gfc_code *result = check_nested_loop_in_chain (ns->code, expr, sym, bad);
   12050          807 :   if (result && !*bad)
   12051              :     {
   12052          519 :       check_nested_loop_in_block_state.expr = expr;
   12053          519 :       check_nested_loop_in_block_state.sym = sym;
   12054          519 :       check_nested_loop_in_block_state.bad = bad;
   12055          519 :       gfc_traverse_ns (ns, check_nested_loop_in_block_symbol);
   12056          519 :       check_nested_loop_in_block_state.expr = NULL;
   12057          519 :       check_nested_loop_in_block_state.sym = NULL;
   12058          519 :       check_nested_loop_in_block_state.bad = NULL;
   12059              :     }
   12060          807 :   return result;
   12061              : }
   12062              : 
   12063              : /* CODE is an OMP loop construct.  Return true if EXPR references
   12064              :    any variables bound in intervening code, to level DEPTH.  */
   12065              : static bool
   12066        22690 : expr_uses_intervening_var (gfc_code *code, int depth, gfc_expr *expr)
   12067              : {
   12068        22690 :   int i;
   12069        22690 :   gfc_code *do_code = code;
   12070              : 
   12071        58156 :   for (i = 0; i < depth; i++)
   12072              :     {
   12073        35469 :       bool bad = false;
   12074        35469 :       do_code = check_nested_loop_in_chain (do_code->block->next,
   12075              :                                             expr, NULL, &bad);
   12076        35469 :       if (bad)
   12077            3 :         return true;
   12078              :     }
   12079              :   return false;
   12080              : }
   12081              : 
   12082              : /* CODE is an OMP loop construct.  Return true if SYM is bound in
   12083              :    intervening code, to level DEPTH.  */
   12084              : static bool
   12085         7573 : is_intervening_var (gfc_code *code, int depth, gfc_symbol *sym)
   12086              : {
   12087         7573 :   int i;
   12088         7573 :   gfc_code *do_code = code;
   12089              : 
   12090        19420 :   for (i = 0; i < depth; i++)
   12091              :     {
   12092        11849 :       bool bad = false;
   12093        11849 :       do_code = check_nested_loop_in_chain (do_code->block->next,
   12094              :                                             NULL, sym, &bad);
   12095        11849 :       if (bad)
   12096            2 :         return true;
   12097              :     }
   12098              :   return false;
   12099              : }
   12100              : 
   12101              : /* CODE is an OMP loop construct.  Return true if EXPR does not reference
   12102              :    any iteration variables outer to level DEPTH.  */
   12103              : static bool
   12104        23769 : expr_is_invariant (gfc_code *code, int depth, gfc_expr *expr)
   12105              : {
   12106        23769 :   int i;
   12107        23769 :   gfc_code *do_code = code;
   12108              : 
   12109        37088 :   for (i = 1; i < depth; i++)
   12110              :     {
   12111        14385 :       do_code = find_nested_loop_in_chain (do_code->block->next);
   12112        14385 :       gcc_assert (do_code);
   12113        14385 :       if (do_code->op == EXEC_OMP_TILE || do_code->op == EXEC_OMP_UNROLL)
   12114              :         {
   12115          136 :           --i;
   12116          136 :           continue;
   12117              :         }
   12118        14249 :       gfc_symbol *ivar = do_code->ext.iterator->var->symtree->n.sym;
   12119        14249 :       if (gfc_find_sym_in_expr (ivar, expr))
   12120              :         return false;
   12121              :     }
   12122              :   return true;
   12123              : }
   12124              : 
   12125              : /* CODE is an OMP loop construct.  Return true if EXPR matches one of the
   12126              :    canonical forms for a bound expression.  It may include references to
   12127              :    an iteration variable outer to level DEPTH; set OUTER_VARP if so.  */
   12128              : static bool
   12129        15137 : bound_expr_is_canonical (gfc_code *code, int depth, gfc_expr *expr,
   12130              :                          gfc_symbol **outer_varp)
   12131              : {
   12132        15137 :   gfc_expr *expr2 = NULL;
   12133              : 
   12134              :   /* Rectangular case.  */
   12135        15137 :   if (depth == 0 || expr_is_invariant (code, depth, expr))
   12136        14569 :     return true;
   12137              : 
   12138              :   /* Any simple variable that didn't pass expr_is_invariant must be
   12139              :      an outer_var.  */
   12140          568 :   if (expr->expr_type == EXPR_VARIABLE && expr->rank == 0)
   12141              :     {
   12142           63 :       *outer_varp = expr->symtree->n.sym;
   12143           63 :       return true;
   12144              :     }
   12145              : 
   12146              :   /* All other permitted forms are binary operators.  */
   12147          505 :   if (expr->expr_type != EXPR_OP)
   12148              :     return false;
   12149              : 
   12150              :   /* Check for plus/minus a loop invariant expr.  */
   12151          503 :   if (expr->value.op.op == INTRINSIC_PLUS
   12152          503 :       || expr->value.op.op == INTRINSIC_MINUS)
   12153              :     {
   12154          483 :       if (expr_is_invariant (code, depth, expr->value.op.op1))
   12155           48 :         expr2 = expr->value.op.op2;
   12156          435 :       else if (expr_is_invariant (code, depth, expr->value.op.op2))
   12157          434 :         expr2 = expr->value.op.op1;
   12158              :       else
   12159              :         return false;
   12160              :     }
   12161              :   else
   12162              :     expr2 = expr;
   12163              : 
   12164              :   /* Check for a product with a loop-invariant expr.  */
   12165          502 :   if (expr2->expr_type == EXPR_OP
   12166           96 :       && expr2->value.op.op == INTRINSIC_TIMES)
   12167              :     {
   12168           96 :       if (expr_is_invariant (code, depth, expr2->value.op.op1))
   12169           40 :         expr2 = expr2->value.op.op2;
   12170           56 :       else if (expr_is_invariant (code, depth, expr2->value.op.op2))
   12171           53 :         expr2 = expr2->value.op.op1;
   12172              :       else
   12173              :         return false;
   12174              :     }
   12175              : 
   12176              :   /* What's left must be a reference to an outer loop variable.  */
   12177          499 :   if (expr2->expr_type == EXPR_VARIABLE
   12178          499 :       && expr2->rank == 0
   12179          998 :       && is_outer_iteration_variable (code, depth, expr2->symtree->n.sym))
   12180              :     {
   12181          499 :       *outer_varp = expr2->symtree->n.sym;
   12182          499 :       return true;
   12183              :     }
   12184              : 
   12185              :   return false;
   12186              : }
   12187              : 
   12188              : static void
   12189         5412 : resolve_omp_do (gfc_code *code)
   12190              : {
   12191         5412 :   gfc_code *do_code, *next;
   12192         5412 :   int list, i, count, non_generated_count;
   12193         5412 :   gfc_omp_namelist *n;
   12194         5412 :   gfc_symbol *dovar;
   12195         5412 :   const char *name;
   12196         5412 :   bool is_simd = false;
   12197         5412 :   bool errorp = false;
   12198         5412 :   bool perfect_nesting_errorp = false;
   12199         5412 :   bool imperfect = false;
   12200              : 
   12201         5412 :   switch (code->op)
   12202              :     {
   12203              :     case EXEC_OMP_DISTRIBUTE: name = "!$OMP DISTRIBUTE"; break;
   12204           49 :     case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
   12205           49 :       name = "!$OMP DISTRIBUTE PARALLEL DO";
   12206           49 :       break;
   12207           32 :     case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
   12208           32 :       name = "!$OMP DISTRIBUTE PARALLEL DO SIMD";
   12209           32 :       is_simd = true;
   12210           32 :       break;
   12211           50 :     case EXEC_OMP_DISTRIBUTE_SIMD:
   12212           50 :       name = "!$OMP DISTRIBUTE SIMD";
   12213           50 :       is_simd = true;
   12214           50 :       break;
   12215         1335 :     case EXEC_OMP_DO: name = "!$OMP DO"; break;
   12216          134 :     case EXEC_OMP_DO_SIMD: name = "!$OMP DO SIMD"; is_simd = true; break;
   12217           64 :     case EXEC_OMP_LOOP: name = "!$OMP LOOP"; break;
   12218         1208 :     case EXEC_OMP_PARALLEL_DO: name = "!$OMP PARALLEL DO"; break;
   12219          304 :     case EXEC_OMP_PARALLEL_DO_SIMD:
   12220          304 :       name = "!$OMP PARALLEL DO SIMD";
   12221          304 :       is_simd = true;
   12222          304 :       break;
   12223           46 :     case EXEC_OMP_PARALLEL_LOOP: name = "!$OMP PARALLEL LOOP"; break;
   12224            7 :     case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
   12225            7 :       name = "!$OMP PARALLEL MASKED TASKLOOP";
   12226            7 :       break;
   12227           10 :     case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
   12228           10 :       name = "!$OMP PARALLEL MASKED TASKLOOP SIMD";
   12229           10 :       is_simd = true;
   12230           10 :       break;
   12231           12 :     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
   12232           12 :       name = "!$OMP PARALLEL MASTER TASKLOOP";
   12233           12 :       break;
   12234           18 :     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
   12235           18 :       name = "!$OMP PARALLEL MASTER TASKLOOP SIMD";
   12236           18 :       is_simd = true;
   12237           18 :       break;
   12238            8 :     case EXEC_OMP_MASKED_TASKLOOP: name = "!$OMP MASKED TASKLOOP"; break;
   12239           14 :     case EXEC_OMP_MASKED_TASKLOOP_SIMD:
   12240           14 :       name = "!$OMP MASKED TASKLOOP SIMD";
   12241           14 :       is_simd = true;
   12242           14 :       break;
   12243           14 :     case EXEC_OMP_MASTER_TASKLOOP: name = "!$OMP MASTER TASKLOOP"; break;
   12244           19 :     case EXEC_OMP_MASTER_TASKLOOP_SIMD:
   12245           19 :       name = "!$OMP MASTER TASKLOOP SIMD";
   12246           19 :       is_simd = true;
   12247           19 :       break;
   12248          783 :     case EXEC_OMP_SIMD: name = "!$OMP SIMD"; is_simd = true; break;
   12249           88 :     case EXEC_OMP_TARGET_PARALLEL_DO: name = "!$OMP TARGET PARALLEL DO"; break;
   12250           19 :     case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
   12251           19 :       name = "!$OMP TARGET PARALLEL DO SIMD";
   12252           19 :       is_simd = true;
   12253           19 :       break;
   12254           16 :     case EXEC_OMP_TARGET_PARALLEL_LOOP:
   12255           16 :       name = "!$OMP TARGET PARALLEL LOOP";
   12256           16 :       break;
   12257           33 :     case EXEC_OMP_TARGET_SIMD:
   12258           33 :       name = "!$OMP TARGET SIMD";
   12259           33 :       is_simd = true;
   12260           33 :       break;
   12261           20 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
   12262           20 :       name = "!$OMP TARGET TEAMS DISTRIBUTE";
   12263           20 :       break;
   12264           75 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
   12265           75 :       name = "!$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO";
   12266           75 :       break;
   12267           37 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
   12268           37 :       name = "!$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD";
   12269           37 :       is_simd = true;
   12270           37 :       break;
   12271           20 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
   12272           20 :       name = "!$OMP TARGET TEAMS DISTRIBUTE SIMD";
   12273           20 :       is_simd = true;
   12274           20 :       break;
   12275           19 :     case EXEC_OMP_TARGET_TEAMS_LOOP: name = "!$OMP TARGET TEAMS LOOP"; break;
   12276           69 :     case EXEC_OMP_TASKLOOP: name = "!$OMP TASKLOOP"; break;
   12277           38 :     case EXEC_OMP_TASKLOOP_SIMD:
   12278           38 :       name = "!$OMP TASKLOOP SIMD";
   12279           38 :       is_simd = true;
   12280           38 :       break;
   12281           20 :     case EXEC_OMP_TEAMS_DISTRIBUTE: name = "!$OMP TEAMS DISTRIBUTE"; break;
   12282           37 :     case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
   12283           37 :       name = "!$OMP TEAMS DISTRIBUTE PARALLEL DO";
   12284           37 :       break;
   12285           60 :     case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
   12286           60 :       name = "!$OMP TEAMS DISTRIBUTE PARALLEL DO SIMD";
   12287           60 :       is_simd = true;
   12288           60 :       break;
   12289           42 :     case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
   12290           42 :       name = "!$OMP TEAMS DISTRIBUTE SIMD";
   12291           42 :       is_simd = true;
   12292           42 :       break;
   12293           48 :     case EXEC_OMP_TEAMS_LOOP: name = "!$OMP TEAMS LOOP"; break;
   12294          195 :     case EXEC_OMP_TILE: name = "!$OMP TILE"; break;
   12295          415 :     case EXEC_OMP_UNROLL: name = "!$OMP UNROLL"; break;
   12296            0 :     default: gcc_unreachable ();
   12297              :     }
   12298              : 
   12299         5412 :   if (code->ext.omp_clauses)
   12300         5412 :     resolve_omp_clauses (code, code->ext.omp_clauses, NULL);
   12301              : 
   12302         5412 :   if (code->op == EXEC_OMP_TILE && code->ext.omp_clauses->sizes_list == NULL)
   12303            0 :     gfc_error ("SIZES clause is required on !$OMP TILE construct at %L",
   12304              :                &code->loc);
   12305              : 
   12306         5412 :   do_code = code->block->next;
   12307         5412 :   if (code->ext.omp_clauses->orderedc)
   12308              :     count = code->ext.omp_clauses->orderedc;
   12309         5268 :   else if (code->ext.omp_clauses->sizes_list)
   12310          195 :     count = gfc_expr_list_len (code->ext.omp_clauses->sizes_list);
   12311              :   else
   12312              :     {
   12313         5073 :       count = code->ext.omp_clauses->collapse;
   12314         5073 :       if (count <= 0)
   12315              :         count = 1;
   12316              :     }
   12317              : 
   12318         5412 :   non_generated_count = count;
   12319              :   /* While the spec defines the loop nest depth independently of the COLLAPSE
   12320              :      clause, in practice the middle end only pays attention to the COLLAPSE
   12321              :      depth and treats any further inner loops as the final-loop-body.  So
   12322              :      here we also check canonical loop nest form only for the number of
   12323              :      outer loops specified by the COLLAPSE clause too.  */
   12324         8051 :   for (i = 1; i <= count; i++)
   12325              :     {
   12326         8051 :       gfc_symbol *start_var = NULL, *end_var = NULL;
   12327              :       /* Parse errors are not recoverable.  */
   12328         8051 :       if (do_code->op == EXEC_DO_WHILE)
   12329              :         {
   12330            6 :           gfc_error ("%s cannot be a DO WHILE or DO without loop control "
   12331              :                      "at %L", name, &do_code->loc);
   12332          106 :           goto fail;
   12333              :         }
   12334         8045 :       if (do_code->op == EXEC_DO_CONCURRENT)
   12335              :         {
   12336            4 :           gfc_error ("%s cannot be a DO CONCURRENT loop at %L", name,
   12337              :                      &do_code->loc);
   12338            4 :           goto fail;
   12339              :         }
   12340         8041 :       if (do_code->op == EXEC_OMP_TILE || do_code->op == EXEC_OMP_UNROLL)
   12341              :         {
   12342          466 :           if (do_code->op == EXEC_OMP_UNROLL)
   12343              :             {
   12344          308 :               if (!do_code->ext.omp_clauses->partial)
   12345              :                 {
   12346           53 :                   gfc_error ("Generated loop of UNROLL construct at %L "
   12347              :                              "without PARTIAL clause does not have "
   12348              :                              "canonical form", &do_code->loc);
   12349           53 :                   goto fail;
   12350              :                 }
   12351          255 :               else if (i != count)
   12352              :                 {
   12353            5 :                   gfc_error ("UNROLL construct at %L with PARTIAL clause "
   12354              :                              "generates just one loop with canonical form "
   12355              :                              "but %d loops are needed",
   12356            5 :                              &do_code->loc, count - i + 1);
   12357            5 :                   goto fail;
   12358              :                 }
   12359              :             }
   12360          158 :           else if (do_code->op == EXEC_OMP_TILE)
   12361              :             {
   12362          158 :               if (do_code->ext.omp_clauses->sizes_list == NULL)
   12363              :                 /* This should have been diagnosed earlier already.  */
   12364            0 :                 return;
   12365          158 :               int l = gfc_expr_list_len (do_code->ext.omp_clauses->sizes_list);
   12366          158 :               if (count - i + 1 > l)
   12367              :                 {
   12368           14 :                   gfc_error ("TILE construct at %L generates %d loops "
   12369              :                              "with canonical form but %d loops are needed",
   12370              :                              &do_code->loc, l, count - i + 1);
   12371           14 :                   goto fail;
   12372              :                 }
   12373              :             }
   12374          394 :           if (do_code->ext.omp_clauses && do_code->ext.omp_clauses->erroneous)
   12375           17 :             goto fail;
   12376          377 :           if (imperfect && !perfect_nesting_errorp)
   12377              :             {
   12378            4 :               sorry_at (gfc_get_location (&do_code->loc),
   12379              :                         "Imperfectly nested loop using generated loops");
   12380            4 :               errorp = true;
   12381              :             }
   12382          377 :           if (non_generated_count == count)
   12383          329 :             non_generated_count = i - 1;
   12384          377 :           --i;
   12385          377 :           do_code = do_code->block->next;
   12386          377 :           continue;
   12387          377 :         }
   12388         7575 :       gcc_assert (do_code->op == EXEC_DO);
   12389         7575 :       if (do_code->ext.iterator->var->ts.type != BT_INTEGER)
   12390              :         {
   12391            3 :           gfc_error ("%s iteration variable must be of type integer at %L",
   12392              :                      name, &do_code->loc);
   12393            3 :           errorp = true;
   12394              :         }
   12395         7575 :       dovar = do_code->ext.iterator->var->symtree->n.sym;
   12396         7575 :       if (dovar->attr.threadprivate)
   12397              :         {
   12398            0 :           gfc_error ("%s iteration variable must not be THREADPRIVATE "
   12399              :                      "at %L", name, &do_code->loc);
   12400            0 :           errorp = true;
   12401              :         }
   12402         7575 :       if (code->ext.omp_clauses)
   12403       303000 :         for (list = 0; list < OMP_LIST_NUM; list++)
   12404        97461 :           if (!is_simd || code->ext.omp_clauses->collapse > 1
   12405       295425 :               ? (list != OMP_LIST_PRIVATE && list != OMP_LIST_LASTPRIVATE
   12406       254319 :                   && list != OMP_LIST_ALLOCATE)
   12407        41106 :               : (list != OMP_LIST_PRIVATE && list != OMP_LIST_LASTPRIVATE
   12408        41106 :                  && list != OMP_LIST_ALLOCATE && list != OMP_LIST_LINEAR))
   12409       276020 :             for (n = code->ext.omp_clauses->lists[list]; n; n = n->next)
   12410         4374 :               if (dovar == n->sym)
   12411              :                 {
   12412            5 :                   if (!is_simd || code->ext.omp_clauses->collapse > 1)
   12413            4 :                     gfc_error ("%s iteration variable present on clause "
   12414              :                                "other than PRIVATE, LASTPRIVATE or "
   12415              :                                "ALLOCATE at %L", name, &do_code->loc);
   12416              :                   else
   12417            1 :                     gfc_error ("%s iteration variable present on clause "
   12418              :                                "other than PRIVATE, LASTPRIVATE, ALLOCATE or "
   12419              :                                "LINEAR at %L", name, &do_code->loc);
   12420              :                   errorp = true;
   12421              :                 }
   12422         7575 :       if (is_outer_iteration_variable (code, i, dovar))
   12423              :         {
   12424            2 :           gfc_error ("%s iteration variable used in more than one loop at %L",
   12425              :                      name, &do_code->loc);
   12426            2 :           errorp = true;
   12427              :         }
   12428         7573 :       else if (is_intervening_var (code, i, dovar))
   12429              :         {
   12430            2 :           gfc_error ("%s iteration variable at %L is bound in "
   12431              :                      "intervening code",
   12432              :                      name, &do_code->loc);
   12433            2 :           errorp = true;
   12434              :         }
   12435         7571 :       else if (!bound_expr_is_canonical (code, i,
   12436         7571 :                                          do_code->ext.iterator->start,
   12437              :                                          &start_var))
   12438              :         {
   12439            4 :           gfc_error ("%s loop start expression not in canonical form at %L",
   12440              :                      name, &do_code->loc);
   12441            4 :           errorp = true;
   12442              :         }
   12443         7567 :       else if (expr_uses_intervening_var (code, i,
   12444         7567 :                                           do_code->ext.iterator->start))
   12445              :         {
   12446            1 :           gfc_error ("%s loop start expression at %L uses variable bound in "
   12447              :                      "intervening code",
   12448              :                      name, &do_code->loc);
   12449            1 :           errorp = true;
   12450              :         }
   12451         7566 :       else if (!bound_expr_is_canonical (code, i,
   12452         7566 :                                          do_code->ext.iterator->end,
   12453              :                                          &end_var))
   12454              :         {
   12455            2 :           gfc_error ("%s loop end expression not in canonical form at %L",
   12456              :                      name, &do_code->loc);
   12457            2 :           errorp = true;
   12458              :         }
   12459         7564 :       else if (expr_uses_intervening_var (code, i,
   12460         7564 :                                           do_code->ext.iterator->end))
   12461              :         {
   12462            1 :           gfc_error ("%s loop end expression at %L uses variable bound in "
   12463              :                      "intervening code",
   12464              :                      name, &do_code->loc);
   12465            1 :           errorp = true;
   12466              :         }
   12467         7563 :       else if (start_var && end_var && start_var != end_var)
   12468              :         {
   12469            1 :           gfc_error ("%s loop bounds reference different "
   12470              :                      "iteration variables at %L", name, &do_code->loc);
   12471            1 :           errorp = true;
   12472              :         }
   12473         7562 :       else if (!expr_is_invariant (code, i, do_code->ext.iterator->step))
   12474              :         {
   12475            3 :           gfc_error ("%s loop increment not in canonical form at %L",
   12476              :                      name, &do_code->loc);
   12477            3 :           errorp = true;
   12478              :         }
   12479         7559 :       else if (expr_uses_intervening_var (code, i,
   12480         7559 :                                           do_code->ext.iterator->step))
   12481              :         {
   12482            1 :           gfc_error ("%s loop increment expression at %L uses variable "
   12483              :                      "bound in intervening code",
   12484              :                      name, &do_code->loc);
   12485            1 :           errorp = true;
   12486              :         }
   12487         7575 :       if (start_var || end_var)
   12488              :         {
   12489          528 :           code->ext.omp_clauses->non_rectangular = 1;
   12490          528 :           if (i > non_generated_count)
   12491              :             {
   12492            3 :               sorry_at (gfc_get_location (&do_code->loc),
   12493              :                         "Non-rectangular loops from generated loops "
   12494              :                         "unsupported");
   12495            3 :               errorp = true;
   12496              :             }
   12497              :         }
   12498              : 
   12499              :       /* Only parse loop body into nested loop and intervening code if
   12500              :          there are supposed to be more loops in the nest to collapse.  */
   12501         7575 :       if (i == count)
   12502              :         break;
   12503              : 
   12504         2269 :       next = find_nested_loop_in_chain (do_code->block->next);
   12505              : 
   12506         2269 :       if (!next)
   12507              :         {
   12508              :           /* Parse error, can't recover from this.  */
   12509            7 :           gfc_error ("not enough DO loops for collapsed %s (level %d) at %L",
   12510              :                      name, i, &code->loc);
   12511            7 :           goto fail;
   12512              :         }
   12513         2262 :       else if (next != do_code->block->next
   12514         2102 :                || (next->next && next->next->op != EXEC_CONTINUE))
   12515              :         /* Imperfectly nested loop found.  */
   12516              :         {
   12517              :           /* Only diagnose violation of imperfect nesting constraints once.  */
   12518          177 :           if (!perfect_nesting_errorp)
   12519              :             {
   12520          176 :               if (code->ext.omp_clauses->orderedc)
   12521              :                 {
   12522            3 :                   gfc_error ("%s inner loops must be perfectly nested with "
   12523              :                              "ORDERED clause at %L",
   12524              :                              name, &code->loc);
   12525            3 :                   perfect_nesting_errorp = true;
   12526              :                 }
   12527          173 :               else if (code->ext.omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN])
   12528              :                 {
   12529            2 :                   gfc_error ("%s inner loops must be perfectly nested with "
   12530              :                              "REDUCTION INSCAN clause at %L",
   12531              :                              name, &code->loc);
   12532            2 :                   perfect_nesting_errorp = true;
   12533              :                 }
   12534          171 :               else if (code->op == EXEC_OMP_TILE)
   12535              :                 {
   12536            8 :                   gfc_error ("%s inner loops must be perfectly nested at %L",
   12537              :                              name, &code->loc);
   12538            8 :                   perfect_nesting_errorp = true;
   12539              :                 }
   12540           13 :               if (perfect_nesting_errorp)
   12541              :                 errorp = true;
   12542              :             }
   12543          177 :           if (diagnose_intervening_code_errors (do_code->block->next,
   12544              :                                                 name, next))
   12545            5 :             errorp = true;
   12546              :           imperfect = true;
   12547              :         }
   12548         2262 :       do_code = next;
   12549              :     }
   12550              : 
   12551              :   /* Give up now if we found any constraint violations.  */
   12552         5306 :   if (errorp)
   12553              :     {
   12554           48 :     fail:
   12555          154 :       if (code->ext.omp_clauses)
   12556          154 :         code->ext.omp_clauses->erroneous = 1;
   12557          154 :       return;
   12558              :     }
   12559              : 
   12560         5258 :   if (non_generated_count)
   12561         4988 :     restructure_intervening_code (&code->block->next, code,
   12562              :                                   non_generated_count);
   12563              : }
   12564              : 
   12565              : /* Resolve the context selector. In particular, SKIP_P is set to true,
   12566              :    the context can never be matched.  */
   12567              : 
   12568              : static void
   12569          763 : gfc_resolve_omp_context_selector (gfc_omp_set_selector *oss,
   12570              :                                   bool is_metadirective, bool *skip_p)
   12571              : {
   12572          763 :   if (skip_p)
   12573          310 :     *skip_p = false;
   12574         1452 :   for (gfc_omp_set_selector *set_selector = oss; set_selector;
   12575          689 :        set_selector = set_selector->next)
   12576         1485 :     for (gfc_omp_selector *os = set_selector->trait_selectors; os; os = os->next)
   12577              :       {
   12578          814 :         if (os->score)
   12579              :           {
   12580           52 :             if (!gfc_resolve_expr (os->score)
   12581           52 :                 || os->score->ts.type != BT_INTEGER
   12582          104 :                 || os->score->rank != 0)
   12583              :               {
   12584            0 :                 gfc_error ("%<score%> argument must be constant integer "
   12585            0 :                            "expression at %L", &os->score->where);
   12586            0 :                 gfc_free_expr (os->score);
   12587            0 :                 os->score = nullptr;
   12588              :               }
   12589           52 :             else if (os->score->expr_type == EXPR_CONSTANT
   12590           52 :                      && mpz_sgn (os->score->value.integer) < 0)
   12591              :               {
   12592            1 :                 gfc_error ("%<score%> argument must be non-negative at %L",
   12593              :                            &os->score->where);
   12594            1 :                 gfc_free_expr (os->score);
   12595            1 :                 os->score = nullptr;
   12596              :               }
   12597              :           }
   12598              : 
   12599          814 :         if (os->code == OMP_TRAIT_INVALID)
   12600              :           break;
   12601          796 :         enum omp_tp_type property_kind = omp_ts_map[os->code].tp_type;
   12602          796 :         gfc_omp_trait_property *otp = os->properties;
   12603              : 
   12604          796 :         if (!otp)
   12605          409 :           continue;
   12606          387 :         switch (property_kind)
   12607              :           {
   12608          139 :           case OMP_TRAIT_PROPERTY_DEV_NUM_EXPR:
   12609          139 :           case OMP_TRAIT_PROPERTY_BOOL_EXPR:
   12610          139 :             if (!gfc_resolve_expr (otp->expr)
   12611          138 :                 || (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR
   12612          124 :                     && otp->expr->ts.type != BT_LOGICAL)
   12613          137 :                 || (property_kind == OMP_TRAIT_PROPERTY_DEV_NUM_EXPR
   12614           14 :                     && otp->expr->ts.type != BT_INTEGER)
   12615          137 :                 || otp->expr->rank != 0
   12616          276 :                 || (!is_metadirective && otp->expr->expr_type != EXPR_CONSTANT))
   12617              :               {
   12618            3 :                 if (is_metadirective)
   12619              :                   {
   12620            0 :                     if (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR)
   12621            0 :                       gfc_error ("property must be a "
   12622              :                                  "logical expression at %L",
   12623            0 :                                  &otp->expr->where);
   12624              :                     else
   12625            0 :                       gfc_error ("property must be an "
   12626              :                                  "integer expression at %L",
   12627            0 :                                  &otp->expr->where);
   12628              :                   }
   12629              :                 else
   12630              :                   {
   12631            3 :                     if (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR)
   12632            2 :                       gfc_error ("property must be a constant "
   12633              :                                  "logical expression at %L",
   12634            2 :                                  &otp->expr->where);
   12635              :                     else
   12636            1 :                       gfc_error ("property must be a constant "
   12637              :                                  "integer expression at %L",
   12638            1 :                                  &otp->expr->where);
   12639              :                   }
   12640              :                 /* Prevent later ICEs. */
   12641            3 :                 gfc_expr *e;
   12642            3 :                 if (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR)
   12643            2 :                   e = gfc_get_logical_expr (gfc_default_logical_kind,
   12644            2 :                                             &otp->expr->where, true);
   12645              :                 else
   12646            1 :                   e = gfc_get_int_expr (gfc_default_integer_kind,
   12647            1 :                                         &otp->expr->where, 0);
   12648            3 :                 gfc_free_expr (otp->expr);
   12649            3 :                 otp->expr = e;
   12650            3 :                 continue;
   12651            3 :               }
   12652              :             /* Device number must be conforming, which includes
   12653              :                omp_initial_device (-1), omp_invalid_device (-4),
   12654              :                and omp_default_device (-5).  */
   12655          136 :             if (property_kind == OMP_TRAIT_PROPERTY_DEV_NUM_EXPR
   12656           14 :                 && otp->expr->expr_type == EXPR_CONSTANT
   12657            5 :                 && mpz_sgn (otp->expr->value.integer) < 0
   12658            3 :                 && mpz_cmp_si (otp->expr->value.integer, -1) != 0
   12659            2 :                 && mpz_cmp_si (otp->expr->value.integer, -4) != 0
   12660            1 :                 && mpz_cmp_si (otp->expr->value.integer, -5) != 0)
   12661            1 :               gfc_error ("property must be a conforming device number at %L",
   12662              :                          &otp->expr->where);
   12663              :             break;
   12664              :           default:
   12665              :             break;
   12666              :           }
   12667              :         /* This only handles one specific case: User condition.
   12668              :            FIXME: Handle more cases by calling omp_context_selector_matches;
   12669              :            unfortunately, we cannot generate the tree here as, e.g., PARM_DECL
   12670              :            backend decl are not available at this stage - but might be used in,
   12671              :            e.g. user conditions. See PR122361.  */
   12672          384 :         if (skip_p && otp
   12673          138 :             && os->code == OMP_TRAIT_USER_CONDITION
   12674           81 :             && otp->expr->expr_type == EXPR_CONSTANT
   12675           14 :             && otp->expr->value.logical == false)
   12676           12 :           *skip_p = true;
   12677              :       }
   12678          763 : }
   12679              : 
   12680              : 
   12681              : static void
   12682          138 : resolve_omp_metadirective (gfc_code *code, gfc_namespace *ns)
   12683              : {
   12684          138 :   gfc_omp_variant *variant = code->ext.omp_variants;
   12685          138 :   gfc_omp_variant *prev_variant = variant;
   12686              : 
   12687          448 :   while (variant)
   12688              :     {
   12689          310 :       bool skip;
   12690          310 :       gfc_resolve_omp_context_selector (variant->selectors, true, &skip);
   12691          310 :       gfc_code *variant_code = variant->code;
   12692          310 :       gfc_resolve_code (variant_code, ns);
   12693          310 :       if (skip)
   12694              :         {
   12695              :           /* The following should only be true if an error occurred
   12696              :              as the 'otherwise' clause should always match.  */
   12697           12 :           if (variant == code->ext.omp_variants && !variant->next)
   12698              :             break;
   12699           12 :           gfc_omp_variant *tmp = variant;
   12700           12 :           if (variant == code->ext.omp_variants)
   12701           11 :             variant = prev_variant = code->ext.omp_variants = variant->next;
   12702              :           else
   12703            1 :             variant = prev_variant->next = variant->next;
   12704           12 :           gfc_free_omp_set_selector_list (tmp->selectors);
   12705           12 :           free (tmp);
   12706              :         }
   12707              :       else
   12708              :         {
   12709          298 :           prev_variant = variant;
   12710          298 :           variant = variant->next;
   12711              :         }
   12712              :     }
   12713              :   /* Replace metadirective by its body if only 'nothing' remains.  */
   12714          138 :   if (!code->ext.omp_variants->next && code->ext.omp_variants->stmt == ST_NONE)
   12715              :     {
   12716           11 :       gfc_code *next = code->next;
   12717           11 :       gfc_code *inner = code->ext.omp_variants->code;
   12718           11 :       gfc_free_omp_set_selector_list (code->ext.omp_variants->selectors);
   12719           11 :       free (code->ext.omp_variants);
   12720           11 :       *code = *inner;
   12721           11 :       free (inner);
   12722           11 :       while (code->next)
   12723              :         code = code->next;
   12724           11 :       code->next = next;
   12725              :     }
   12726          138 : }
   12727              : 
   12728              : 
   12729              : static gfc_statement
   12730           63 : omp_code_to_statement (gfc_code *code)
   12731              : {
   12732           63 :   switch (code->op)
   12733              :     {
   12734              :     case EXEC_OMP_PARALLEL:
   12735              :       return ST_OMP_PARALLEL;
   12736            0 :     case EXEC_OMP_PARALLEL_MASKED:
   12737            0 :       return ST_OMP_PARALLEL_MASKED;
   12738            0 :     case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
   12739            0 :       return ST_OMP_PARALLEL_MASKED_TASKLOOP;
   12740            0 :     case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
   12741            0 :       return ST_OMP_PARALLEL_MASKED_TASKLOOP_SIMD;
   12742            0 :     case EXEC_OMP_PARALLEL_MASTER:
   12743            0 :       return ST_OMP_PARALLEL_MASTER;
   12744            0 :     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
   12745            0 :       return ST_OMP_PARALLEL_MASTER_TASKLOOP;
   12746            0 :     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
   12747            0 :       return ST_OMP_PARALLEL_MASTER_TASKLOOP_SIMD;
   12748            1 :     case EXEC_OMP_PARALLEL_SECTIONS:
   12749            1 :       return ST_OMP_PARALLEL_SECTIONS;
   12750            1 :     case EXEC_OMP_SECTIONS:
   12751            1 :       return ST_OMP_SECTIONS;
   12752            1 :     case EXEC_OMP_ORDERED:
   12753            1 :       return ST_OMP_ORDERED;
   12754            1 :     case EXEC_OMP_CRITICAL:
   12755            1 :       return ST_OMP_CRITICAL;
   12756            0 :     case EXEC_OMP_MASKED:
   12757            0 :       return ST_OMP_MASKED;
   12758            0 :     case EXEC_OMP_MASKED_TASKLOOP:
   12759            0 :       return ST_OMP_MASKED_TASKLOOP;
   12760            0 :     case EXEC_OMP_MASKED_TASKLOOP_SIMD:
   12761            0 :       return ST_OMP_MASKED_TASKLOOP_SIMD;
   12762            1 :     case EXEC_OMP_MASTER:
   12763            1 :       return ST_OMP_MASTER;
   12764            0 :     case EXEC_OMP_MASTER_TASKLOOP:
   12765            0 :       return ST_OMP_MASTER_TASKLOOP;
   12766            0 :     case EXEC_OMP_MASTER_TASKLOOP_SIMD:
   12767            0 :       return ST_OMP_MASTER_TASKLOOP_SIMD;
   12768            1 :     case EXEC_OMP_SINGLE:
   12769            1 :       return ST_OMP_SINGLE;
   12770            1 :     case EXEC_OMP_TASK:
   12771            1 :       return ST_OMP_TASK;
   12772            1 :     case EXEC_OMP_WORKSHARE:
   12773            1 :       return ST_OMP_WORKSHARE;
   12774            1 :     case EXEC_OMP_PARALLEL_WORKSHARE:
   12775            1 :       return ST_OMP_PARALLEL_WORKSHARE;
   12776            3 :     case EXEC_OMP_DO:
   12777            3 :       return ST_OMP_DO;
   12778            0 :     case EXEC_OMP_LOOP:
   12779            0 :       return ST_OMP_LOOP;
   12780            0 :     case EXEC_OMP_ALLOCATE:
   12781            0 :       return ST_OMP_ALLOCATE_EXEC;
   12782            0 :     case EXEC_OMP_ALLOCATORS:
   12783            0 :       return ST_OMP_ALLOCATORS;
   12784            0 :     case EXEC_OMP_ASSUME:
   12785            0 :       return ST_OMP_ASSUME;
   12786            1 :     case EXEC_OMP_ATOMIC:
   12787            1 :       return ST_OMP_ATOMIC;
   12788            1 :     case EXEC_OMP_BARRIER:
   12789            1 :       return ST_OMP_BARRIER;
   12790            1 :     case EXEC_OMP_CANCEL:
   12791            1 :       return ST_OMP_CANCEL;
   12792            1 :     case EXEC_OMP_CANCELLATION_POINT:
   12793            1 :       return ST_OMP_CANCELLATION_POINT;
   12794            0 :     case EXEC_OMP_ERROR:
   12795            0 :       return ST_OMP_ERROR;
   12796            1 :     case EXEC_OMP_FLUSH:
   12797            1 :       return ST_OMP_FLUSH;
   12798            0 :     case EXEC_OMP_INTEROP:
   12799            0 :       return ST_OMP_INTEROP;
   12800            1 :     case EXEC_OMP_DISTRIBUTE:
   12801            1 :       return ST_OMP_DISTRIBUTE;
   12802            1 :     case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
   12803            1 :       return ST_OMP_DISTRIBUTE_PARALLEL_DO;
   12804            1 :     case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
   12805            1 :       return ST_OMP_DISTRIBUTE_PARALLEL_DO_SIMD;
   12806            1 :     case EXEC_OMP_DISTRIBUTE_SIMD:
   12807            1 :       return ST_OMP_DISTRIBUTE_SIMD;
   12808            1 :     case EXEC_OMP_DO_SIMD:
   12809            1 :       return ST_OMP_DO_SIMD;
   12810            0 :     case EXEC_OMP_SCAN:
   12811            0 :       return ST_OMP_SCAN;
   12812            0 :     case EXEC_OMP_SCOPE:
   12813            0 :       return ST_OMP_SCOPE;
   12814            1 :     case EXEC_OMP_SIMD:
   12815            1 :       return ST_OMP_SIMD;
   12816            1 :     case EXEC_OMP_TARGET:
   12817            1 :       return ST_OMP_TARGET;
   12818            1 :     case EXEC_OMP_TARGET_DATA:
   12819            1 :       return ST_OMP_TARGET_DATA;
   12820            1 :     case EXEC_OMP_TARGET_ENTER_DATA:
   12821            1 :       return ST_OMP_TARGET_ENTER_DATA;
   12822            1 :     case EXEC_OMP_TARGET_EXIT_DATA:
   12823            1 :       return ST_OMP_TARGET_EXIT_DATA;
   12824            1 :     case EXEC_OMP_TARGET_PARALLEL:
   12825            1 :       return ST_OMP_TARGET_PARALLEL;
   12826            1 :     case EXEC_OMP_TARGET_PARALLEL_DO:
   12827            1 :       return ST_OMP_TARGET_PARALLEL_DO;
   12828            1 :     case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
   12829            1 :       return ST_OMP_TARGET_PARALLEL_DO_SIMD;
   12830            0 :     case EXEC_OMP_TARGET_PARALLEL_LOOP:
   12831            0 :       return ST_OMP_TARGET_PARALLEL_LOOP;
   12832            1 :     case EXEC_OMP_TARGET_SIMD:
   12833            1 :       return ST_OMP_TARGET_SIMD;
   12834            1 :     case EXEC_OMP_TARGET_TEAMS:
   12835            1 :       return ST_OMP_TARGET_TEAMS;
   12836            1 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
   12837            1 :       return ST_OMP_TARGET_TEAMS_DISTRIBUTE;
   12838            1 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
   12839            1 :       return ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO;
   12840            1 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
   12841            1 :       return ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD;
   12842            1 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
   12843            1 :       return ST_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD;
   12844            0 :     case EXEC_OMP_TARGET_TEAMS_LOOP:
   12845            0 :       return ST_OMP_TARGET_TEAMS_LOOP;
   12846            1 :     case EXEC_OMP_TARGET_UPDATE:
   12847            1 :       return ST_OMP_TARGET_UPDATE;
   12848            1 :     case EXEC_OMP_TASKGROUP:
   12849            1 :       return ST_OMP_TASKGROUP;
   12850            1 :     case EXEC_OMP_TASKLOOP:
   12851            1 :       return ST_OMP_TASKLOOP;
   12852            1 :     case EXEC_OMP_TASKLOOP_SIMD:
   12853            1 :       return ST_OMP_TASKLOOP_SIMD;
   12854            1 :     case EXEC_OMP_TASKWAIT:
   12855            1 :       return ST_OMP_TASKWAIT;
   12856            1 :     case EXEC_OMP_TASKYIELD:
   12857            1 :       return ST_OMP_TASKYIELD;
   12858            1 :     case EXEC_OMP_TEAMS:
   12859            1 :       return ST_OMP_TEAMS;
   12860            1 :     case EXEC_OMP_TEAMS_DISTRIBUTE:
   12861            1 :       return ST_OMP_TEAMS_DISTRIBUTE;
   12862            1 :     case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
   12863            1 :       return ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO;
   12864            1 :     case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
   12865            1 :       return ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD;
   12866            1 :     case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
   12867            1 :       return ST_OMP_TEAMS_DISTRIBUTE_SIMD;
   12868            0 :     case EXEC_OMP_TEAMS_LOOP:
   12869            0 :       return ST_OMP_TEAMS_LOOP;
   12870            6 :     case EXEC_OMP_PARALLEL_DO:
   12871            6 :       return ST_OMP_PARALLEL_DO;
   12872            1 :     case EXEC_OMP_PARALLEL_DO_SIMD:
   12873            1 :       return ST_OMP_PARALLEL_DO_SIMD;
   12874            0 :     case EXEC_OMP_PARALLEL_LOOP:
   12875            0 :       return ST_OMP_PARALLEL_LOOP;
   12876            1 :     case EXEC_OMP_DEPOBJ:
   12877            1 :       return ST_OMP_DEPOBJ;
   12878            0 :     case EXEC_OMP_TILE:
   12879            0 :       return ST_OMP_TILE;
   12880            0 :     case EXEC_OMP_UNROLL:
   12881            0 :       return ST_OMP_UNROLL;
   12882            0 :     case EXEC_OMP_DISPATCH:
   12883            0 :       return ST_OMP_DISPATCH;
   12884            0 :     default:
   12885            0 :       gcc_unreachable ();
   12886              :     }
   12887              : }
   12888              : 
   12889              : static gfc_statement
   12890           63 : oacc_code_to_statement (gfc_code *code)
   12891              : {
   12892           63 :   switch (code->op)
   12893              :     {
   12894              :     case EXEC_OACC_PARALLEL:
   12895              :       return ST_OACC_PARALLEL;
   12896              :     case EXEC_OACC_KERNELS:
   12897              :       return ST_OACC_KERNELS;
   12898              :     case EXEC_OACC_SERIAL:
   12899              :       return ST_OACC_SERIAL;
   12900              :     case EXEC_OACC_DATA:
   12901              :       return ST_OACC_DATA;
   12902              :     case EXEC_OACC_HOST_DATA:
   12903              :       return ST_OACC_HOST_DATA;
   12904              :     case EXEC_OACC_PARALLEL_LOOP:
   12905              :       return ST_OACC_PARALLEL_LOOP;
   12906              :     case EXEC_OACC_KERNELS_LOOP:
   12907              :       return ST_OACC_KERNELS_LOOP;
   12908              :     case EXEC_OACC_SERIAL_LOOP:
   12909              :       return ST_OACC_SERIAL_LOOP;
   12910              :     case EXEC_OACC_LOOP:
   12911              :       return ST_OACC_LOOP;
   12912              :     case EXEC_OACC_ATOMIC:
   12913              :       return ST_OACC_ATOMIC;
   12914              :     case EXEC_OACC_ROUTINE:
   12915              :       return ST_OACC_ROUTINE;
   12916              :     case EXEC_OACC_UPDATE:
   12917              :       return ST_OACC_UPDATE;
   12918              :     case EXEC_OACC_WAIT:
   12919              :       return ST_OACC_WAIT;
   12920              :     case EXEC_OACC_CACHE:
   12921              :       return ST_OACC_CACHE;
   12922              :     case EXEC_OACC_ENTER_DATA:
   12923              :       return ST_OACC_ENTER_DATA;
   12924              :     case EXEC_OACC_EXIT_DATA:
   12925              :       return ST_OACC_EXIT_DATA;
   12926              :     case EXEC_OACC_DECLARE:
   12927              :       return ST_OACC_DECLARE;
   12928            0 :     default:
   12929            0 :       gcc_unreachable ();
   12930              :     }
   12931              : }
   12932              : 
   12933              : static void
   12934        13160 : resolve_oacc_directive_inside_omp_region (gfc_code *code)
   12935              : {
   12936        13160 :   if (omp_current_ctx != NULL && omp_current_ctx->is_openmp)
   12937              :     {
   12938           11 :       gfc_statement st = omp_code_to_statement (omp_current_ctx->code);
   12939           11 :       gfc_statement oacc_st = oacc_code_to_statement (code);
   12940           11 :       gfc_error ("The %s directive cannot be specified within "
   12941              :                  "a %s region at %L", gfc_ascii_statement (oacc_st),
   12942              :                  gfc_ascii_statement (st), &code->loc);
   12943              :     }
   12944        13160 : }
   12945              : 
   12946              : static void
   12947        20762 : resolve_omp_directive_inside_oacc_region (gfc_code *code)
   12948              : {
   12949        20762 :   if (omp_current_ctx != NULL && !omp_current_ctx->is_openmp)
   12950              :     {
   12951           52 :       gfc_statement st = oacc_code_to_statement (omp_current_ctx->code);
   12952           52 :       gfc_statement omp_st = omp_code_to_statement (code);
   12953           52 :       gfc_error ("The %s directive cannot be specified within "
   12954              :                  "a %s region at %L", gfc_ascii_statement (omp_st),
   12955              :                  gfc_ascii_statement (st), &code->loc);
   12956              :     }
   12957        20762 : }
   12958              : 
   12959              : 
   12960              : static void
   12961         5270 : resolve_oacc_nested_loops (gfc_code *code, gfc_code* do_code, int collapse,
   12962              :                           const char *clause)
   12963              : {
   12964         5270 :   gfc_symbol *dovar;
   12965         5270 :   gfc_code *c;
   12966         5270 :   int i;
   12967              : 
   12968         5790 :   for (i = 1; i <= collapse; i++)
   12969              :     {
   12970         5790 :       if (do_code->op == EXEC_DO_WHILE)
   12971              :         {
   12972           10 :           gfc_error ("!$ACC LOOP cannot be a DO WHILE or DO without loop control "
   12973              :                      "at %L", &do_code->loc);
   12974           10 :           break;
   12975              :         }
   12976         5780 :       if (do_code->op == EXEC_DO_CONCURRENT)
   12977              :         {
   12978            3 :           gfc_error ("!$ACC LOOP cannot be a DO CONCURRENT loop at %L",
   12979              :                      &do_code->loc);
   12980            3 :           break;
   12981              :         }
   12982         5777 :       gcc_assert (do_code->op == EXEC_DO);
   12983         5777 :       if (do_code->ext.iterator->var->ts.type != BT_INTEGER)
   12984            6 :         gfc_error ("!$ACC LOOP iteration variable must be of type integer at %L",
   12985              :                    &do_code->loc);
   12986         5777 :       dovar = do_code->ext.iterator->var->symtree->n.sym;
   12987         5777 :       if (i > 1)
   12988              :         {
   12989          518 :           gfc_code *do_code2 = code->block->next;
   12990          518 :           int j;
   12991              : 
   12992         1218 :           for (j = 1; j < i; j++)
   12993              :             {
   12994          710 :               gfc_symbol *ivar = do_code2->ext.iterator->var->symtree->n.sym;
   12995          710 :               if (dovar == ivar
   12996          710 :                   || gfc_find_sym_in_expr (ivar, do_code->ext.iterator->start)
   12997          701 :                   || gfc_find_sym_in_expr (ivar, do_code->ext.iterator->end)
   12998         1410 :                   || gfc_find_sym_in_expr (ivar, do_code->ext.iterator->step))
   12999              :                 {
   13000           10 :                   gfc_error ("!$ACC LOOP %s loops don't form rectangular "
   13001              :                              "iteration space at %L", clause, &do_code->loc);
   13002           10 :                   break;
   13003              :                 }
   13004          700 :               do_code2 = do_code2->block->next;
   13005              :             }
   13006              :         }
   13007         5777 :       if (i == collapse)
   13008              :         break;
   13009          577 :       for (c = do_code->next; c; c = c->next)
   13010           48 :         if (c->op != EXEC_NOP && c->op != EXEC_CONTINUE)
   13011              :           {
   13012            0 :             gfc_error ("%s !$ACC LOOP loops not perfectly nested at %L",
   13013              :                        clause, &c->loc);
   13014            0 :             break;
   13015              :           }
   13016          529 :       if (c)
   13017              :         break;
   13018          529 :       do_code = do_code->block;
   13019          529 :       if (do_code->op != EXEC_DO && do_code->op != EXEC_DO_WHILE
   13020            0 :           && do_code->op != EXEC_DO_CONCURRENT)
   13021              :         {
   13022            0 :           gfc_error ("not enough DO loops for %s !$ACC LOOP at %L",
   13023              :                      clause, &code->loc);
   13024            0 :           break;
   13025              :         }
   13026          529 :       do_code = do_code->next;
   13027          529 :       if (do_code == NULL
   13028          522 :           || (do_code->op != EXEC_DO && do_code->op != EXEC_DO_WHILE
   13029            2 :               && do_code->op != EXEC_DO_CONCURRENT))
   13030              :         {
   13031            9 :           gfc_error ("not enough DO loops for %s !$ACC LOOP at %L",
   13032              :                      clause, &code->loc);
   13033            9 :           break;
   13034              :         }
   13035              :     }
   13036         5270 : }
   13037              : 
   13038              : 
   13039              : static void
   13040        10115 : resolve_oacc_loop_blocks (gfc_code *code)
   13041              : {
   13042        10115 :   if (!oacc_is_loop (code))
   13043              :     return;
   13044              : 
   13045         5270 :   if (code->ext.omp_clauses->tile_list && code->ext.omp_clauses->gang
   13046           24 :       && code->ext.omp_clauses->worker && code->ext.omp_clauses->vector)
   13047            0 :     gfc_error ("Tiled loop cannot be parallelized across gangs, workers and "
   13048              :                "vectors at the same time at %L", &code->loc);
   13049              : 
   13050         5270 :   if (code->ext.omp_clauses->tile_list)
   13051              :     {
   13052              :       gfc_expr_list *el;
   13053          501 :       for (el = code->ext.omp_clauses->tile_list; el; el = el->next)
   13054              :         {
   13055          304 :           if (el->expr == NULL)
   13056              :             {
   13057              :               /* NULL expressions are used to represent '*' arguments.
   13058              :                  Convert those to a 0 expressions.  */
   13059          113 :               el->expr = gfc_get_constant_expr (BT_INTEGER,
   13060              :                                                 gfc_default_integer_kind,
   13061              :                                                 &code->loc);
   13062          113 :               mpz_set_si (el->expr->value.integer, 0);
   13063              :             }
   13064              :           else
   13065              :             {
   13066          191 :               resolve_positive_int_expr (el->expr, "TILE");
   13067          191 :               if (el->expr->expr_type != EXPR_CONSTANT)
   13068           14 :                 gfc_error ("TILE requires constant expression at %L",
   13069              :                            &code->loc);
   13070              :             }
   13071              :         }
   13072              :     }
   13073              : }
   13074              : 
   13075              : 
   13076              : void
   13077        10115 : gfc_resolve_oacc_blocks (gfc_code *code, gfc_namespace *ns)
   13078              : {
   13079        10115 :   fortran_omp_context ctx;
   13080        10115 :   gfc_omp_clauses *omp_clauses = code->ext.omp_clauses;
   13081        10115 :   gfc_omp_namelist *n;
   13082        10115 :   int list;
   13083              : 
   13084        10115 :   resolve_oacc_loop_blocks (code);
   13085              : 
   13086        10115 :   ctx.code = code;
   13087        10115 :   ctx.sharing_clauses = new hash_set<gfc_symbol *>;
   13088        10115 :   ctx.private_iterators = new hash_set<gfc_symbol *>;
   13089        10115 :   ctx.previous = omp_current_ctx;
   13090        10115 :   ctx.is_openmp = false;
   13091        10115 :   omp_current_ctx = &ctx;
   13092              : 
   13093       404600 :   for (list = 0; list < OMP_LIST_NUM; list++)
   13094       394485 :     switch (list)
   13095              :       {
   13096        10115 :       case OMP_LIST_PRIVATE:
   13097        10704 :         for (n = omp_clauses->lists[list]; n; n = n->next)
   13098          589 :           ctx.sharing_clauses->add (n->sym);
   13099              :         break;
   13100              :       default:
   13101              :         break;
   13102              :       }
   13103              : 
   13104        10115 :   gfc_resolve_blocks (code->block, ns);
   13105              : 
   13106        10115 :   omp_current_ctx = ctx.previous;
   13107        20230 :   delete ctx.sharing_clauses;
   13108        20230 :   delete ctx.private_iterators;
   13109        10115 : }
   13110              : 
   13111              : 
   13112              : static void
   13113         5270 : resolve_oacc_loop (gfc_code *code)
   13114              : {
   13115         5270 :   gfc_code *do_code;
   13116         5270 :   int collapse;
   13117              : 
   13118         5270 :   if (code->ext.omp_clauses)
   13119         5270 :     resolve_omp_clauses (code, code->ext.omp_clauses, NULL, true);
   13120              : 
   13121         5270 :   do_code = code->block->next;
   13122         5270 :   collapse = code->ext.omp_clauses->collapse;
   13123              : 
   13124              :   /* Both collapsed and tiled loops are lowered the same way, but are not
   13125              :      compatible.  In gfc_trans_omp_do, the tile is prioritized.  */
   13126         5270 :   if (code->ext.omp_clauses->tile_list)
   13127              :     {
   13128              :       int num = 0;
   13129              :       gfc_expr_list *el;
   13130          501 :       for (el = code->ext.omp_clauses->tile_list; el; el = el->next)
   13131          304 :         ++num;
   13132          197 :       resolve_oacc_nested_loops (code, code->block->next, num, "tiled");
   13133          197 :       return;
   13134              :     }
   13135              : 
   13136         5073 :   if (collapse <= 0)
   13137              :     collapse = 1;
   13138         5073 :   resolve_oacc_nested_loops (code, do_code, collapse, "collapsed");
   13139              : }
   13140              : 
   13141              : void
   13142       330629 : gfc_resolve_oacc_declare (gfc_namespace *ns)
   13143              : {
   13144       330629 :   int list;
   13145       330629 :   gfc_omp_namelist *n;
   13146       330629 :   gfc_oacc_declare *oc;
   13147              : 
   13148       330629 :   if (ns->oacc_declare == NULL)
   13149              :     return;
   13150              : 
   13151          286 :   for (oc = ns->oacc_declare; oc; oc = oc->next)
   13152              :     {
   13153         6400 :       for (list = 0; list < OMP_LIST_NUM; list++)
   13154         6492 :         for (n = oc->clauses->lists[list]; n; n = n->next)
   13155              :           {
   13156          252 :             n->sym->mark = 0;
   13157          252 :             if (n->sym->attr.flavor != FL_VARIABLE
   13158           16 :                 && (n->sym->attr.flavor != FL_PROCEDURE
   13159            8 :                     || n->sym->result != n->sym))
   13160              :               {
   13161           14 :                 if (n->sym->attr.flavor != FL_PARAMETER)
   13162              :                   {
   13163            8 :                     gfc_error ("Object %qs is not a variable at %L",
   13164              :                                n->sym->name, &oc->loc);
   13165            8 :                     continue;
   13166              :                   }
   13167              :                 /* Note that OpenACC 3.4 permits name constants, but the
   13168              :                    implementation is permitted to ignore the clause;
   13169              :                    as semantically, device_resident kind of makes sense
   13170              :                    (and the wording with it is a bit odd), the warning
   13171              :                    is suppressed.  */
   13172            6 :                 if (list != OMP_LIST_DEVICE_RESIDENT)
   13173            5 :                   gfc_warning (OPT_Wsurprising, "Object %qs at %L is ignored as"
   13174              :                                " parameters need not be copied", n->sym->name,
   13175              :                                &oc->loc);
   13176              :               }
   13177              : 
   13178          244 :             if (n->expr && n->expr->ref->type == REF_ARRAY)
   13179              :               {
   13180            1 :                 gfc_error ("Array sections: %qs not allowed in"
   13181            1 :                            " !$ACC DECLARE at %L", n->sym->name, &oc->loc);
   13182            1 :                 continue;
   13183              :               }
   13184              :           }
   13185              : 
   13186          250 :       for (n = oc->clauses->lists[OMP_LIST_DEVICE_RESIDENT]; n; n = n->next)
   13187           90 :         check_array_not_assumed (n->sym, oc->loc, "DEVICE_RESIDENT");
   13188              :     }
   13189              : 
   13190          286 :   for (oc = ns->oacc_declare; oc; oc = oc->next)
   13191              :     {
   13192         6400 :       for (list = 0; list < OMP_LIST_NUM; list++)
   13193         6492 :         for (n = oc->clauses->lists[list]; n; n = n->next)
   13194              :           {
   13195          252 :             if (n->sym->mark)
   13196              :               {
   13197            9 :                 gfc_error ("Symbol %qs present on multiple clauses at %L",
   13198              :                            n->sym->name, &oc->loc);
   13199            9 :                 continue;
   13200              :               }
   13201              :             else
   13202          243 :               n->sym->mark = 1;
   13203              :           }
   13204              :     }
   13205              : 
   13206          286 :   for (oc = ns->oacc_declare; oc; oc = oc->next)
   13207              :     {
   13208         6400 :       for (list = 0; list < OMP_LIST_NUM; list++)
   13209         6492 :         for (n = oc->clauses->lists[list]; n; n = n->next)
   13210          252 :           n->sym->mark = 0;
   13211              :     }
   13212              : }
   13213              : 
   13214              : 
   13215              : void
   13216       330629 : gfc_resolve_oacc_routines (gfc_namespace *ns)
   13217              : {
   13218       330629 :   for (gfc_oacc_routine_name *orn = ns->oacc_routine_names;
   13219       330729 :        orn;
   13220          100 :        orn = orn->next)
   13221              :     {
   13222          100 :       gfc_symbol *sym = orn->sym;
   13223          100 :       if (!sym->attr.external
   13224           29 :           && !sym->attr.function
   13225           27 :           && !sym->attr.subroutine)
   13226              :         {
   13227            7 :           gfc_error ("NAME %qs does not refer to a subroutine or function"
   13228              :                      " in !$ACC ROUTINE ( NAME ) at %L", sym->name, &orn->loc);
   13229            7 :           continue;
   13230              :         }
   13231           93 :       if (!gfc_add_omp_declare_target (&sym->attr, sym->name, &orn->loc))
   13232              :         {
   13233           20 :           gfc_error ("NAME %qs invalid"
   13234              :                      " in !$ACC ROUTINE ( NAME ) at %L", sym->name, &orn->loc);
   13235           20 :           continue;
   13236              :         }
   13237              :     }
   13238       330629 : }
   13239              : 
   13240              : 
   13241              : void
   13242        13160 : gfc_resolve_oacc_directive (gfc_code *code, gfc_namespace *ns ATTRIBUTE_UNUSED)
   13243              : {
   13244        13160 :   resolve_oacc_directive_inside_omp_region (code);
   13245              : 
   13246        13160 :   switch (code->op)
   13247              :     {
   13248         7347 :     case EXEC_OACC_PARALLEL:
   13249         7347 :     case EXEC_OACC_KERNELS:
   13250         7347 :     case EXEC_OACC_SERIAL:
   13251         7347 :     case EXEC_OACC_DATA:
   13252         7347 :     case EXEC_OACC_HOST_DATA:
   13253         7347 :     case EXEC_OACC_UPDATE:
   13254         7347 :     case EXEC_OACC_ENTER_DATA:
   13255         7347 :     case EXEC_OACC_EXIT_DATA:
   13256         7347 :     case EXEC_OACC_WAIT:
   13257         7347 :     case EXEC_OACC_CACHE:
   13258         7347 :       resolve_omp_clauses (code, code->ext.omp_clauses, NULL, true);
   13259         7347 :       break;
   13260         5270 :     case EXEC_OACC_PARALLEL_LOOP:
   13261         5270 :     case EXEC_OACC_KERNELS_LOOP:
   13262         5270 :     case EXEC_OACC_SERIAL_LOOP:
   13263         5270 :     case EXEC_OACC_LOOP:
   13264         5270 :       resolve_oacc_loop (code);
   13265         5270 :       break;
   13266          543 :     case EXEC_OACC_ATOMIC:
   13267          543 :       resolve_omp_atomic (code);
   13268          543 :       break;
   13269              :     default:
   13270              :       break;
   13271              :     }
   13272        13160 : }
   13273              : 
   13274              : 
   13275              : static void
   13276         1913 : resolve_omp_target (gfc_code *code)
   13277              : {
   13278              : #define GFC_IS_TEAMS_CONSTRUCT(op)                      \
   13279              :   (op == EXEC_OMP_TEAMS                                 \
   13280              :    || op == EXEC_OMP_TEAMS_DISTRIBUTE                   \
   13281              :    || op == EXEC_OMP_TEAMS_DISTRIBUTE_SIMD              \
   13282              :    || op == EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO       \
   13283              :    || op == EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD  \
   13284              :    || op == EXEC_OMP_TEAMS_LOOP)
   13285              : 
   13286         1913 :   if (!code->ext.omp_clauses->contains_teams_construct)
   13287              :     return;
   13288          203 :   gfc_code *c = code->block->next;
   13289          203 :   if (c->op == EXEC_BLOCK)
   13290           30 :     c = c->ext.block.ns->code;
   13291          203 :   if (code->ext.omp_clauses->target_first_st_is_teams_or_meta)
   13292              :     {
   13293          192 :       if (c->op == EXEC_OMP_METADIRECTIVE)
   13294              :         {
   13295           15 :           struct gfc_omp_variant *mc
   13296              :             = c->ext.omp_variants;
   13297              :           /* All mc->(next...->)code should be identical with regards
   13298              :              to the diagnostic below.  */
   13299           16 :           do
   13300              :             {
   13301           16 :               if (mc->stmt != ST_NONE
   13302           15 :                   && GFC_IS_TEAMS_CONSTRUCT (mc->code->op))
   13303              :                 {
   13304           14 :                   if (c->next == NULL && mc->code->next == NULL)
   13305              :                     return;
   13306              :                   c = mc->code;
   13307              :                   break;
   13308              :                 }
   13309            2 :               mc = mc->next;
   13310              :             }
   13311            2 :           while (mc);
   13312              :         }
   13313          177 :       else if (GFC_IS_TEAMS_CONSTRUCT (c->op) && c->next == NULL)
   13314              :         return;
   13315              :     }
   13316              : 
   13317           31 :   while (c && !GFC_IS_TEAMS_CONSTRUCT (c->op))
   13318            8 :     c = c->next;
   13319           23 :   if (c)
   13320           19 :     gfc_error ("!$OMP TARGET region at %L with a nested TEAMS at %L may not "
   13321              :                "contain any other statement, declaration or directive outside "
   13322              :                "of the single TEAMS construct", &c->loc, &code->loc);
   13323              :   else
   13324            4 :     gfc_error ("!$OMP TARGET region at %L with a nested TEAMS may not "
   13325              :                "contain any other statement, declaration or directive outside "
   13326              :                "of the single TEAMS construct", &code->loc);
   13327              : #undef GFC_IS_TEAMS_CONSTRUCT
   13328              : }
   13329              : 
   13330              : static void
   13331          154 : resolve_omp_dispatch (gfc_code *code)
   13332              : {
   13333          154 :   gfc_code *next = code->block->next;
   13334          154 :   if (next == NULL)
   13335              :     return;
   13336              : 
   13337          151 :   gfc_exec_op op = next->op;
   13338          151 :   gcc_assert (op == EXEC_CALL || op == EXEC_ASSIGN);
   13339          151 :   if (op != EXEC_CALL
   13340           74 :       && (op != EXEC_ASSIGN || next->expr2->expr_type != EXPR_FUNCTION))
   13341            3 :     gfc_error (
   13342              :       "%<OMP DISPATCH%> directive at %L must be followed by a procedure "
   13343              :       "call with optional assignment",
   13344              :       &code->loc);
   13345              : 
   13346           77 :   if ((op == EXEC_CALL && next->resolved_sym != NULL
   13347           76 :        && next->resolved_sym->attr.proc_pointer)
   13348          150 :       || (op == EXEC_ASSIGN && gfc_expr_attr (next->expr2).proc_pointer))
   13349            1 :     gfc_error ("%<OMP DISPATCH%> directive at %L cannot be followed by a "
   13350              :                "procedure pointer",
   13351              :                &code->loc);
   13352              : }
   13353              : 
   13354              : /* Resolve OpenMP directive clauses and check various requirements
   13355              :    of each directive.  */
   13356              : 
   13357              : void
   13358        20762 : gfc_resolve_omp_directive (gfc_code *code, gfc_namespace *ns)
   13359              : {
   13360        20762 :   resolve_omp_directive_inside_oacc_region (code);
   13361              : 
   13362        20762 :   if (code->op != EXEC_OMP_ATOMIC)
   13363        18608 :     gfc_maybe_initialize_eh ();
   13364              : 
   13365        20762 :   switch (code->op)
   13366              :     {
   13367         5412 :     case EXEC_OMP_DISTRIBUTE:
   13368         5412 :     case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
   13369         5412 :     case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
   13370         5412 :     case EXEC_OMP_DISTRIBUTE_SIMD:
   13371         5412 :     case EXEC_OMP_DO:
   13372         5412 :     case EXEC_OMP_DO_SIMD:
   13373         5412 :     case EXEC_OMP_LOOP:
   13374         5412 :     case EXEC_OMP_PARALLEL_DO:
   13375         5412 :     case EXEC_OMP_PARALLEL_DO_SIMD:
   13376         5412 :     case EXEC_OMP_PARALLEL_LOOP:
   13377         5412 :     case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
   13378         5412 :     case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
   13379         5412 :     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
   13380         5412 :     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
   13381         5412 :     case EXEC_OMP_MASKED_TASKLOOP:
   13382         5412 :     case EXEC_OMP_MASKED_TASKLOOP_SIMD:
   13383         5412 :     case EXEC_OMP_MASTER_TASKLOOP:
   13384         5412 :     case EXEC_OMP_MASTER_TASKLOOP_SIMD:
   13385         5412 :     case EXEC_OMP_SIMD:
   13386         5412 :     case EXEC_OMP_TARGET_PARALLEL_DO:
   13387         5412 :     case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
   13388         5412 :     case EXEC_OMP_TARGET_PARALLEL_LOOP:
   13389         5412 :     case EXEC_OMP_TARGET_SIMD:
   13390         5412 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
   13391         5412 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
   13392         5412 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
   13393         5412 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
   13394         5412 :     case EXEC_OMP_TARGET_TEAMS_LOOP:
   13395         5412 :     case EXEC_OMP_TASKLOOP:
   13396         5412 :     case EXEC_OMP_TASKLOOP_SIMD:
   13397         5412 :     case EXEC_OMP_TEAMS_DISTRIBUTE:
   13398         5412 :     case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
   13399         5412 :     case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
   13400         5412 :     case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
   13401         5412 :     case EXEC_OMP_TEAMS_LOOP:
   13402         5412 :     case EXEC_OMP_TILE:
   13403         5412 :     case EXEC_OMP_UNROLL:
   13404         5412 :       resolve_omp_do (code);
   13405         5412 :       break;
   13406         1913 :     case EXEC_OMP_TARGET:
   13407         1913 :       resolve_omp_target (code);
   13408         9823 :       gcc_fallthrough ();
   13409         9823 :     case EXEC_OMP_ALLOCATE:
   13410         9823 :     case EXEC_OMP_ALLOCATORS:
   13411         9823 :     case EXEC_OMP_ASSUME:
   13412         9823 :     case EXEC_OMP_CANCEL:
   13413         9823 :     case EXEC_OMP_ERROR:
   13414         9823 :     case EXEC_OMP_INTEROP:
   13415         9823 :     case EXEC_OMP_MASKED:
   13416         9823 :     case EXEC_OMP_ORDERED:
   13417         9823 :     case EXEC_OMP_PARALLEL_WORKSHARE:
   13418         9823 :     case EXEC_OMP_PARALLEL:
   13419         9823 :     case EXEC_OMP_PARALLEL_MASKED:
   13420         9823 :     case EXEC_OMP_PARALLEL_MASTER:
   13421         9823 :     case EXEC_OMP_PARALLEL_SECTIONS:
   13422         9823 :     case EXEC_OMP_SCOPE:
   13423         9823 :     case EXEC_OMP_SECTIONS:
   13424         9823 :     case EXEC_OMP_SINGLE:
   13425         9823 :     case EXEC_OMP_TARGET_DATA:
   13426         9823 :     case EXEC_OMP_TARGET_ENTER_DATA:
   13427         9823 :     case EXEC_OMP_TARGET_EXIT_DATA:
   13428         9823 :     case EXEC_OMP_TARGET_PARALLEL:
   13429         9823 :     case EXEC_OMP_TARGET_TEAMS:
   13430         9823 :     case EXEC_OMP_TASK:
   13431         9823 :     case EXEC_OMP_TASKWAIT:
   13432         9823 :     case EXEC_OMP_TEAMS:
   13433         9823 :     case EXEC_OMP_WORKSHARE:
   13434         9823 :     case EXEC_OMP_DEPOBJ:
   13435         9823 :       if (code->ext.omp_clauses)
   13436         9690 :         resolve_omp_clauses (code, code->ext.omp_clauses, NULL);
   13437              :       break;
   13438         1704 :     case EXEC_OMP_TARGET_UPDATE:
   13439         1704 :       if (code->ext.omp_clauses)
   13440         1704 :         resolve_omp_clauses (code, code->ext.omp_clauses, NULL);
   13441         1704 :       if (code->ext.omp_clauses == NULL
   13442         1704 :           || (code->ext.omp_clauses->lists[OMP_LIST_TO] == NULL
   13443          992 :               && code->ext.omp_clauses->lists[OMP_LIST_FROM] == NULL))
   13444            0 :         gfc_error ("OMP TARGET UPDATE at %L requires at least one TO or "
   13445              :                    "FROM clause", &code->loc);
   13446              :       break;
   13447         2154 :     case EXEC_OMP_ATOMIC:
   13448         2154 :       resolve_omp_clauses (code, code->block->ext.omp_clauses, NULL);
   13449         2154 :       resolve_omp_atomic (code);
   13450         2154 :       break;
   13451          159 :     case EXEC_OMP_CRITICAL:
   13452          159 :       resolve_omp_clauses (code, code->ext.omp_clauses, NULL);
   13453          159 :       if (!code->ext.omp_clauses->critical_name
   13454          112 :           && code->ext.omp_clauses->hint
   13455            3 :           && code->ext.omp_clauses->hint->ts.type == BT_INTEGER
   13456            3 :           && code->ext.omp_clauses->hint->expr_type == EXPR_CONSTANT
   13457            3 :           && mpz_sgn (code->ext.omp_clauses->hint->value.integer) != 0)
   13458            1 :         gfc_error ("OMP CRITICAL at %L with HINT clause requires a NAME, "
   13459              :                    "except when omp_sync_hint_none is used", &code->loc);
   13460              :       break;
   13461           49 :     case EXEC_OMP_SCAN:
   13462              :       /* Flag is only used to checking, hence, it is unset afterwards.  */
   13463           49 :       if (!code->ext.omp_clauses->if_present)
   13464           10 :         gfc_error ("Unexpected !$OMP SCAN at %L outside loop construct with "
   13465              :                    "%<inscan%> REDUCTION clause", &code->loc);
   13466           49 :       code->ext.omp_clauses->if_present = false;
   13467           49 :       resolve_omp_clauses (code, code->ext.omp_clauses, ns);
   13468           49 :       break;
   13469          154 :     case EXEC_OMP_DISPATCH:
   13470          154 :       if (code->ext.omp_clauses)
   13471          154 :         resolve_omp_clauses (code, code->ext.omp_clauses, ns);
   13472          154 :       resolve_omp_dispatch (code);
   13473          154 :       break;
   13474          138 :     case EXEC_OMP_METADIRECTIVE:
   13475          138 :       resolve_omp_metadirective (code, ns);
   13476          138 :       break;
   13477              :     default:
   13478              :       break;
   13479              :     }
   13480        20762 : }
   13481              : 
   13482              : /* Resolve !$omp declare {variant|simd} constructs in NS.
   13483              :    Note that !$omp declare target is resolved in resolve_symbol.  */
   13484              : 
   13485              : void
   13486       341858 : gfc_resolve_omp_declare (gfc_namespace *ns)
   13487              : {
   13488       341858 :   gfc_omp_declare_simd *ods;
   13489       342094 :   for (ods = ns->omp_declare_simd; ods; ods = ods->next)
   13490              :     {
   13491          236 :       if (ods->proc_name != NULL
   13492          196 :           && ods->proc_name != ns->proc_name)
   13493            6 :         gfc_error ("!$OMP DECLARE SIMD should refer to containing procedure "
   13494              :                    "%qs at %L", ns->proc_name->name, &ods->where);
   13495          236 :       if (ods->clauses)
   13496          218 :         resolve_omp_clauses (NULL, ods->clauses, ns);
   13497              :     }
   13498              : 
   13499       341858 :   gfc_omp_declare_variant *odv;
   13500       341858 :   gfc_omp_namelist *range_begin = NULL;
   13501              : 
   13502       342311 :   for (odv = ns->omp_declare_variant; odv; odv = odv->next)
   13503          453 :     gfc_resolve_omp_context_selector (odv->set_selectors, false, nullptr);
   13504       342311 :   for (odv = ns->omp_declare_variant; odv; odv = odv->next)
   13505          656 :     for (gfc_omp_namelist *n = odv->adjust_args_list; n != NULL; n = n->next)
   13506              :       {
   13507          203 :         if ((n->expr == NULL
   13508            6 :              && (range_begin
   13509            4 :                  || n->u.adj_args.range_start
   13510            1 :                  || n->u.adj_args.omp_num_args_plus
   13511            1 :                  || n->u.adj_args.omp_num_args_minus))
   13512          198 :             || n->u.adj_args.error_p)
   13513              :           {
   13514              :           }
   13515          197 :         else if (range_begin
   13516          191 :                  || n->u.adj_args.range_start
   13517          186 :                  || n->u.adj_args.omp_num_args_plus
   13518          186 :                  || n->u.adj_args.omp_num_args_minus)
   13519              :           {
   13520           11 :             if (!n->expr
   13521           11 :                 || !gfc_resolve_expr (n->expr)
   13522           11 :                 || n->expr->expr_type != EXPR_CONSTANT
   13523           10 :                 || n->expr->ts.type != BT_INTEGER
   13524           10 :                 || n->expr->rank != 0
   13525           10 :                 || mpz_sgn (n->expr->value.integer) < 0
   13526           20 :                 || ((n->u.adj_args.omp_num_args_plus
   13527            8 :                      || n->u.adj_args.omp_num_args_minus)
   13528            5 :                     && mpz_sgn (n->expr->value.integer) == 0))
   13529              :               {
   13530            2 :                 if (n->u.adj_args.omp_num_args_plus
   13531            2 :                     || n->u.adj_args.omp_num_args_minus)
   13532            0 :                   gfc_error ("Expected constant non-negative scalar integer "
   13533              :                              "offset expression at %L", &n->where);
   13534              :                 else
   13535            2 :                   gfc_error ("For range-based %<adjust_args%>, a constant "
   13536              :                              "positive scalar integer expression is required "
   13537              :                              "at %L", &n->where);
   13538              :               }
   13539              :           }
   13540          186 :         else if (n->expr
   13541          186 :                  && n->expr->expr_type == EXPR_CONSTANT
   13542           21 :                  && n->expr->ts.type == BT_INTEGER
   13543           20 :                  && mpz_sgn (n->expr->value.integer) > 0)
   13544              :           {
   13545              :           }
   13546          166 :         else if (!n->expr
   13547          166 :                  || !gfc_resolve_expr (n->expr)
   13548          331 :                  || n->expr->expr_type != EXPR_VARIABLE)
   13549            2 :           gfc_error ("Expected dummy parameter name or a positive integer "
   13550              :                      "at %L", &n->where);
   13551          164 :         else if (n->expr->expr_type == EXPR_VARIABLE)
   13552          164 :           n->sym = n->expr->symtree->n.sym;
   13553              : 
   13554          203 :         range_begin = n->u.adj_args.range_start ? n : NULL;
   13555              :       }
   13556       341858 : }
   13557              : 
   13558              : struct omp_udr_callback_data
   13559              : {
   13560              :   gfc_omp_udr *omp_udr;
   13561              :   bool is_initializer;
   13562              : };
   13563              : 
   13564              : static int
   13565         3598 : omp_udr_callback (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
   13566              :                   void *data)
   13567              : {
   13568         3598 :   struct omp_udr_callback_data *cd = (struct omp_udr_callback_data *) data;
   13569         3598 :   if ((*e)->expr_type == EXPR_VARIABLE)
   13570              :     {
   13571         2203 :       if (cd->is_initializer)
   13572              :         {
   13573          535 :           if ((*e)->symtree->n.sym != cd->omp_udr->omp_priv
   13574          140 :               && (*e)->symtree->n.sym != cd->omp_udr->omp_orig)
   13575            4 :             gfc_error ("Variable other than OMP_PRIV or OMP_ORIG used in "
   13576              :                        "INITIALIZER clause of !$OMP DECLARE REDUCTION at %L",
   13577              :                        &(*e)->where);
   13578              :         }
   13579              :       else
   13580              :         {
   13581         1668 :           if ((*e)->symtree->n.sym != cd->omp_udr->omp_out
   13582          597 :               && (*e)->symtree->n.sym != cd->omp_udr->omp_in)
   13583            6 :             gfc_error ("Variable other than OMP_OUT or OMP_IN used in "
   13584              :                        "combiner of !$OMP DECLARE REDUCTION at %L",
   13585              :                        &(*e)->where);
   13586              :         }
   13587              :     }
   13588         3598 :   return 0;
   13589              : }
   13590              : 
   13591              : /* Resolve !$omp declare reduction constructs.  */
   13592              : 
   13593              : static void
   13594          600 : gfc_resolve_omp_udr (gfc_omp_udr *omp_udr)
   13595              : {
   13596          600 :   gfc_actual_arglist *a;
   13597          600 :   const char *predef_name = NULL;
   13598              : 
   13599          600 :   switch (omp_udr->rop)
   13600              :     {
   13601          599 :     case OMP_REDUCTION_PLUS:
   13602          599 :     case OMP_REDUCTION_TIMES:
   13603          599 :     case OMP_REDUCTION_MINUS:
   13604          599 :     case OMP_REDUCTION_AND:
   13605          599 :     case OMP_REDUCTION_OR:
   13606          599 :     case OMP_REDUCTION_EQV:
   13607          599 :     case OMP_REDUCTION_NEQV:
   13608          599 :     case OMP_REDUCTION_MAX:
   13609          599 :     case OMP_REDUCTION_USER:
   13610          599 :       break;
   13611            1 :     default:
   13612            1 :       gfc_error ("Invalid operator for !$OMP DECLARE REDUCTION %s at %L",
   13613              :                  omp_udr->name, &omp_udr->where);
   13614           22 :       return;
   13615              :     }
   13616              : 
   13617          599 :   if (gfc_omp_udr_predef (omp_udr->rop, omp_udr->name,
   13618              :                           &omp_udr->ts, &predef_name))
   13619              :     {
   13620           18 :       if (predef_name)
   13621           18 :         gfc_error_now ("Redefinition of predefined %s "
   13622              :                        "!$OMP DECLARE REDUCTION at %L",
   13623              :                        predef_name, &omp_udr->where);
   13624              :       else
   13625            0 :         gfc_error_now ("Redefinition of predefined "
   13626              :                        "!$OMP DECLARE REDUCTION at %L", &omp_udr->where);
   13627           18 :       return;
   13628              :     }
   13629              : 
   13630          581 :   if (omp_udr->ts.type == BT_CHARACTER
   13631           62 :       && omp_udr->ts.u.cl->length
   13632           32 :       && omp_udr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
   13633              :     {
   13634            1 :       gfc_error ("CHARACTER length in !$OMP DECLARE REDUCTION %s not "
   13635              :                  "constant at %L", omp_udr->name, &omp_udr->where);
   13636            1 :       return;
   13637              :     }
   13638              : 
   13639          580 :   struct omp_udr_callback_data cd;
   13640          580 :   cd.omp_udr = omp_udr;
   13641          580 :   cd.is_initializer = false;
   13642          580 :   gfc_code_walker (&omp_udr->combiner_ns->code, gfc_dummy_code_callback,
   13643              :                    omp_udr_callback, &cd);
   13644          580 :   if (omp_udr->combiner_ns->code->op == EXEC_CALL)
   13645              :     {
   13646          346 :       for (a = omp_udr->combiner_ns->code->ext.actual; a; a = a->next)
   13647          237 :         if (a->expr == NULL)
   13648              :           break;
   13649          110 :       if (a)
   13650            1 :         gfc_error ("Subroutine call with alternate returns in combiner "
   13651              :                    "of !$OMP DECLARE REDUCTION at %L",
   13652              :                    &omp_udr->combiner_ns->code->loc);
   13653              :     }
   13654          580 :   if (omp_udr->initializer_ns)
   13655              :     {
   13656          373 :       cd.is_initializer = true;
   13657          373 :       gfc_code_walker (&omp_udr->initializer_ns->code, gfc_dummy_code_callback,
   13658              :                        omp_udr_callback, &cd);
   13659          373 :       if (omp_udr->initializer_ns->code->op == EXEC_CALL)
   13660              :         {
   13661          377 :           for (a = omp_udr->initializer_ns->code->ext.actual; a; a = a->next)
   13662          243 :             if (a->expr == NULL)
   13663              :               break;
   13664          135 :           if (a)
   13665            1 :             gfc_error ("Subroutine call with alternate returns in "
   13666              :                        "INITIALIZER clause of !$OMP DECLARE REDUCTION "
   13667              :                        "at %L", &omp_udr->initializer_ns->code->loc);
   13668          136 :           for (a = omp_udr->initializer_ns->code->ext.actual; a; a = a->next)
   13669          135 :             if (a->expr
   13670          135 :                 && a->expr->expr_type == EXPR_VARIABLE
   13671          135 :                 && a->expr->symtree->n.sym == omp_udr->omp_priv
   13672          134 :                 && a->expr->ref == NULL)
   13673              :               break;
   13674          135 :           if (a == NULL)
   13675            1 :             gfc_error ("One of actual subroutine arguments in INITIALIZER "
   13676              :                        "clause of !$OMP DECLARE REDUCTION must be OMP_PRIV "
   13677              :                        "at %L", &omp_udr->initializer_ns->code->loc);
   13678              :         }
   13679              :     }
   13680          207 :   else if (omp_udr->ts.type == BT_DERIVED
   13681          207 :            && !gfc_has_default_initializer (omp_udr->ts.u.derived))
   13682              :     {
   13683            1 :       gfc_error ("Missing INITIALIZER clause for !$OMP DECLARE REDUCTION "
   13684              :                  "of derived type without default initializer at %L",
   13685              :                  &omp_udr->where);
   13686            1 :       return;
   13687              :     }
   13688              : }
   13689              : 
   13690              : void
   13691       342866 : gfc_resolve_omp_udrs (gfc_symtree *st)
   13692              : {
   13693       342866 :   gfc_omp_udr *omp_udr;
   13694              : 
   13695       342866 :   if (st == NULL)
   13696              :     return;
   13697          504 :   gfc_resolve_omp_udrs (st->left);
   13698          504 :   gfc_resolve_omp_udrs (st->right);
   13699         1104 :   for (omp_udr = st->n.omp_udr; omp_udr; omp_udr = omp_udr->next)
   13700          600 :     gfc_resolve_omp_udr (omp_udr);
   13701              : }
        

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.