LCOV - code coverage report
Current view: top level - gcc/fortran - trans-openmp.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 96.0 % 6309 6057
Test Date: 2026-08-01 15:33:25 Functions: 100.0 % 121 121
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* OpenMP directive translation -- generate GCC trees from gfc_code.
       2              :    Copyright (C) 2005-2026 Free Software Foundation, Inc.
       3              :    Contributed by Jakub Jelinek <jakub@redhat.com>
       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              : 
      22              : #include "config.h"
      23              : #include "system.h"
      24              : #include "coretypes.h"
      25              : #include "options.h"
      26              : #include "tree.h"
      27              : #include "gfortran.h"
      28              : #include "basic-block.h"
      29              : #include "tree-ssa.h"
      30              : #include "tree-ssa-loop-niter.h"  /* for simplify_replace_tree.  */
      31              : #include "function.h"
      32              : #include "gimple.h"
      33              : #include "gimple-expr.h"
      34              : #include "trans.h"
      35              : #include "stringpool.h"
      36              : #include "fold-const.h"
      37              : #include "gimplify.h" /* For create_tmp_var_raw.  */
      38              : #include "trans-stmt.h"
      39              : #include "trans-types.h"
      40              : #include "trans-array.h"
      41              : #include "trans-const.h"
      42              : #include "trans-descriptor.h"
      43              : #include "arith.h"
      44              : #include "constructor.h"
      45              : #include "gomp-constants.h"
      46              : #include "omp-general.h"
      47              : #include "omp-low.h"
      48              : #include "memmodel.h"  /* For MEMMODEL_ enums.  */
      49              : #include "dependency.h"
      50              : #include "gimple-iterator.h" /* For gsi_iterator_update.  */
      51              : #include "gimplify-me.h"  /* For force_gimple_operand.  */
      52              : 
      53              : #undef GCC_DIAG_STYLE
      54              : #define GCC_DIAG_STYLE __gcc_tdiag__
      55              : #include "diagnostic-core.h"
      56              : #undef GCC_DIAG_STYLE
      57              : #define GCC_DIAG_STYLE __gcc_gfc__
      58              : #include "attribs.h"
      59              : #include "function.h"
      60              : 
      61              : int ompws_flags;
      62              : 
      63              : /* True if OpenMP should regard this DECL as being a scalar which has Fortran's
      64              :    allocatable or pointer attribute.  */
      65              : 
      66              : bool
      67         5967 : gfc_omp_is_allocatable_or_ptr (const_tree decl)
      68              : {
      69         5967 :   return (DECL_P (decl)
      70         5967 :           && (GFC_DECL_GET_SCALAR_POINTER (decl)
      71         4236 :               || GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)));
      72              : }
      73              : 
      74              : /* True if the argument is an optional argument; except that false is also
      75              :    returned for arguments with the value attribute (nonpointers) and for
      76              :    assumed-shape variables (decl is a local variable containing arg->data).
      77              :    Note that for 'procedure(), optional' the value false is used as that's
      78              :    always a pointer and no additional indirection is used.
      79              :    Note that pvoid_type_node is for 'type(c_ptr), value' (and c_funloc).  */
      80              : 
      81              : static bool
      82        46778 : gfc_omp_is_optional_argument (const_tree decl)
      83              : {
      84              :   /* Note: VAR_DECL can occur with BIND(C) and array descriptors.  */
      85        30977 :   return ((TREE_CODE (decl) == PARM_DECL || VAR_P (decl))
      86        46778 :           && DECL_LANG_SPECIFIC (decl)
      87        21055 :           && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
      88        20871 :           && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl)))
      89        20636 :           && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) != FUNCTION_TYPE
      90        67389 :           && GFC_DECL_OPTIONAL_ARGUMENT (decl));
      91              : }
      92              : 
      93              : /* Check whether this DECL belongs to a Fortran optional argument.
      94              :    With 'for_present_check' set to false, decls which are optional parameters
      95              :    themselves are returned as tree - or a NULL_TREE otherwise. Those decls are
      96              :    always pointers.  With 'for_present_check' set to true, the decl for checking
      97              :    whether an argument is present is returned; for arguments with value
      98              :    attribute this is the hidden argument and of BOOLEAN_TYPE.  If the decl is
      99              :    unrelated to optional arguments, NULL_TREE is returned.  */
     100              : 
     101              : tree
     102        22697 : gfc_omp_check_optional_argument (tree decl, bool for_present_check)
     103              : {
     104        22697 :   if (!for_present_check)
     105         2176 :     return gfc_omp_is_optional_argument (decl) ? decl : NULL_TREE;
     106              : 
     107        20521 :   if (!DECL_LANG_SPECIFIC (decl))
     108              :     return NULL_TREE;
     109              : 
     110         5425 :   tree orig_decl = decl;
     111              : 
     112              :   /* For assumed-shape arrays, a local decl with arg->data is used.  */
     113         5425 :   if (TREE_CODE (decl) != PARM_DECL
     114         5425 :       && (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl))
     115         2021 :           || GFC_ARRAY_TYPE_P (TREE_TYPE (decl))))
     116          811 :     decl = GFC_DECL_SAVED_DESCRIPTOR (decl);
     117              : 
     118              :   /* Note: With BIND(C), array descriptors are converted to a VAR_DECL.  */
     119         5425 :   if (decl == NULL_TREE
     120         5288 :       || (TREE_CODE (decl) != PARM_DECL && TREE_CODE (decl) != VAR_DECL)
     121         5288 :       || !DECL_LANG_SPECIFIC (decl)
     122        10242 :       || !GFC_DECL_OPTIONAL_ARGUMENT (decl))
     123              :     return NULL_TREE;
     124              : 
     125              :    /* Scalars with VALUE attribute which are passed by value use a hidden
     126              :       argument to denote the present status.  They are passed as nonpointer type
     127              :       with one exception: 'type(c_ptr), value' as 'void*'.  */
     128              :    /* Cf. trans-expr.cc's gfc_conv_expr_present.  */
     129         2834 :    if (TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE
     130         2834 :        || VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
     131              :     {
     132          205 :       char name[GFC_MAX_SYMBOL_LEN + 2];
     133          205 :       tree tree_name;
     134              : 
     135          205 :       name[0] = '.';
     136          205 :       strcpy (&name[1], IDENTIFIER_POINTER (DECL_NAME (decl)));
     137          205 :       tree_name = get_identifier (name);
     138              : 
     139              :       /* Walk function argument list to find the hidden arg.  */
     140          205 :       decl = DECL_ARGUMENTS (DECL_CONTEXT (decl));
     141         1437 :       for ( ; decl != NULL_TREE; decl = TREE_CHAIN (decl))
     142         1437 :         if (DECL_NAME (decl) == tree_name
     143         1437 :             && DECL_ARTIFICIAL (decl))
     144              :           break;
     145              : 
     146          205 :       gcc_assert (decl);
     147          205 :       return decl;
     148              :     }
     149              : 
     150         2629 :   return fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
     151         2629 :                           orig_decl, null_pointer_node);
     152              : }
     153              : 
     154              : 
     155              : /* Returns tree with NULL if it is not an array descriptor and with the tree to
     156              :    access the 'data' component otherwise.  With type_only = true, it returns the
     157              :    TREE_TYPE without creating a new tree.  */
     158              : 
     159              : tree
     160        19923 : gfc_omp_array_data (tree decl, bool type_only)
     161              : {
     162        19923 :   tree type = TREE_TYPE (decl);
     163              : 
     164        19923 :   if (POINTER_TYPE_P (type))
     165        10270 :     type = TREE_TYPE (type);
     166              : 
     167        19923 :   if (!GFC_DESCRIPTOR_TYPE_P (type))
     168              :     return NULL_TREE;
     169              : 
     170         4621 :   if (type_only)
     171         3396 :     return GFC_TYPE_ARRAY_DATAPTR_TYPE (type);
     172              : 
     173         1225 :   if (POINTER_TYPE_P (TREE_TYPE (decl)))
     174          419 :     decl = build_fold_indirect_ref (decl);
     175              : 
     176         1225 :   decl = gfc_conv_descriptor_data_get (decl);
     177         1225 :   STRIP_NOPS (decl);
     178         1225 :   return decl;
     179              : }
     180              : 
     181              : /* Returns true if DECL is an array for which the actual array data has to be
     182              :    privatized; the caller must ensure that DECL is an array descriptor,
     183              :    i.e. 'omp_array_data' returns true.  */
     184              : 
     185              : bool
     186           93 : gfc_omp_array_data_privatize (tree decl)
     187              : {
     188           93 :   tree type = TREE_TYPE (decl);
     189              : 
     190           93 :   if (POINTER_TYPE_P (type))
     191            3 :     type = TREE_TYPE (type);
     192              : 
     193           93 :   gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
     194              : 
     195           93 :   return (GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_POINTER
     196           93 :           && GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_POINTER_CONT);
     197              : }
     198              : 
     199              : /* Return the byte-size of the passed array descriptor. */
     200              : 
     201              : tree
     202           23 : gfc_omp_array_size (tree decl, gimple_seq *pre_p)
     203              : {
     204           23 :   stmtblock_t block;
     205           23 :   if (POINTER_TYPE_P (TREE_TYPE (decl)))
     206           23 :     decl = build_fold_indirect_ref (decl);
     207           23 :   tree type = TREE_TYPE (decl);
     208           23 :   gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
     209           23 :   bool allocatable = (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE
     210            0 :                       || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER
     211           23 :                       || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT);
     212           23 :   gfc_init_block (&block);
     213           69 :   tree size = gfc_full_array_size (&block, decl,
     214           23 :                                    GFC_TYPE_ARRAY_RANK (TREE_TYPE (decl)));
     215           23 :   size = fold_convert (size_type_node, size);
     216           23 :   tree elemsz = gfc_get_element_type (TREE_TYPE (decl));
     217           23 :   if (TREE_CODE (elemsz) == ARRAY_TYPE && TYPE_STRING_FLAG (elemsz))
     218            6 :     elemsz = gfc_conv_descriptor_elem_len_get (decl);
     219              :   else
     220           17 :     elemsz = TYPE_SIZE_UNIT (elemsz);
     221           23 :   size = fold_build2 (MULT_EXPR, size_type_node, size, elemsz);
     222           23 :   if (!allocatable)
     223            0 :     gimplify_and_add (gfc_finish_block (&block), pre_p);
     224              :   else
     225              :     {
     226           23 :       tree var = create_tmp_var (size_type_node);
     227           23 :       gfc_add_expr_to_block (&block, build2 (MODIFY_EXPR, sizetype, var, size));
     228           23 :       tree tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
     229              :                                   gfc_conv_descriptor_data_get (decl),
     230              :                                   null_pointer_node);
     231           23 :       tmp = build3_loc (input_location, COND_EXPR, void_type_node, tmp,
     232              :                         gfc_finish_block (&block),
     233              :                         build2 (MODIFY_EXPR, sizetype, var, size_zero_node));
     234           23 :       gimplify_and_add (tmp, pre_p);
     235           23 :       size = var;
     236              :     }
     237           23 :   return size;
     238              : }
     239              : 
     240              : 
     241              : /* True if OpenMP should privatize what this DECL points to rather
     242              :    than the DECL itself.  */
     243              : 
     244              : bool
     245       463530 : gfc_omp_privatize_by_reference (const_tree decl)
     246              : {
     247       463530 :   tree type = TREE_TYPE (decl);
     248              : 
     249       463530 :   if (TREE_CODE (type) == REFERENCE_TYPE
     250       463530 :       && (!DECL_ARTIFICIAL (decl) || TREE_CODE (decl) == PARM_DECL))
     251              :     return true;
     252              : 
     253       440546 :   if (TREE_CODE (type) == POINTER_TYPE
     254       440546 :       && gfc_omp_is_optional_argument (decl))
     255              :     return true;
     256              : 
     257       431461 :   if (TREE_CODE (type) == POINTER_TYPE)
     258              :     {
     259        33303 :       while (TREE_CODE (decl) == COMPONENT_REF)
     260            0 :         decl = TREE_OPERAND (decl, 1);
     261              : 
     262              :       /* Array POINTER/ALLOCATABLE have aggregate types, all user variables
     263              :          that have POINTER_TYPE type and aren't scalar pointers, scalar
     264              :          allocatables, Cray pointees or C pointers are supposed to be
     265              :          privatized by reference.  */
     266        33303 :       if (GFC_DECL_GET_SCALAR_POINTER (decl)
     267        31788 :           || GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
     268        29434 :           || GFC_DECL_CRAY_POINTEE (decl)
     269        29428 :           || GFC_DECL_ASSOCIATE_VAR_P (decl)
     270        38996 :           || VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
     271              :         return false;
     272              : 
     273        21354 :       if (!DECL_ARTIFICIAL (decl)
     274        21354 :           && TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE)
     275              :         return true;
     276              : 
     277              :       /* Some arrays are expanded as DECL_ARTIFICIAL pointers
     278              :          by the frontend.  */
     279        13817 :       if (DECL_LANG_SPECIFIC (decl)
     280        13817 :           && GFC_DECL_SAVED_DESCRIPTOR (decl))
     281              :         return true;
     282              :     }
     283              : 
     284              :   return false;
     285              : }
     286              : 
     287              : /* OMP_CLAUSE_DEFAULT_UNSPECIFIED unless OpenMP sharing attribute
     288              :    of DECL is predetermined.  */
     289              : 
     290              : enum omp_clause_default_kind
     291         8510 : gfc_omp_predetermined_sharing (tree decl)
     292              : {
     293              :   /* Associate names preserve the association established during ASSOCIATE.
     294              :      As they are implemented either as pointers to the selector or array
     295              :      descriptor and shouldn't really change in the ASSOCIATE region,
     296              :      this decl can be either shared or firstprivate.  If it is a pointer,
     297              :      use firstprivate, as it is cheaper that way, otherwise make it shared.  */
     298         8510 :   if (GFC_DECL_ASSOCIATE_VAR_P (decl))
     299              :     {
     300           45 :       if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE)
     301              :         return OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
     302              :       else
     303           18 :         return OMP_CLAUSE_DEFAULT_SHARED;
     304              :     }
     305              : 
     306         8465 :   if (DECL_ARTIFICIAL (decl)
     307         1585 :       && ! GFC_DECL_RESULT (decl)
     308        10026 :       && ! (DECL_LANG_SPECIFIC (decl)
     309          375 :             && GFC_DECL_SAVED_DESCRIPTOR (decl)))
     310              :     return OMP_CLAUSE_DEFAULT_SHARED;
     311              : 
     312              :   /* Cray pointees shouldn't be listed in any clauses and should be
     313              :      gimplified to dereference of the corresponding Cray pointer.
     314              :      Make them all private, so that they are emitted in the debug
     315              :      information.  */
     316         7230 :   if (GFC_DECL_CRAY_POINTEE (decl))
     317              :     return OMP_CLAUSE_DEFAULT_PRIVATE;
     318              : 
     319              :   /* Assumed-size arrays are predetermined shared.  */
     320         7194 :   if (TREE_CODE (decl) == PARM_DECL
     321         2011 :       && GFC_ARRAY_TYPE_P (TREE_TYPE (decl))
     322          716 :       && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (decl)) == GFC_ARRAY_UNKNOWN
     323         7910 :       && GFC_TYPE_ARRAY_UBOUND (TREE_TYPE (decl),
     324              :                                 GFC_TYPE_ARRAY_RANK (TREE_TYPE (decl)) - 1)
     325              :          == NULL)
     326              :     return OMP_CLAUSE_DEFAULT_SHARED;
     327              : 
     328              :   /* Dummy procedures aren't considered variables by OpenMP, thus are
     329              :      disallowed in OpenMP clauses.  They are represented as PARM_DECLs
     330              :      in the middle-end, so return OMP_CLAUSE_DEFAULT_FIRSTPRIVATE here
     331              :      to avoid complaining about their uses with default(none).  */
     332         7126 :   if (TREE_CODE (decl) == PARM_DECL
     333         1943 :       && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
     334         7911 :       && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == FUNCTION_TYPE)
     335              :     return OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
     336              : 
     337              :   /* COMMON and EQUIVALENCE decls are shared.  They
     338              :      are only referenced through DECL_VALUE_EXPR of the variables
     339              :      contained in them.  If those are privatized, they will not be
     340              :      gimplified to the COMMON or EQUIVALENCE decls.  */
     341         7110 :   if (GFC_DECL_COMMON_OR_EQUIV (decl) && ! DECL_HAS_VALUE_EXPR_P (decl))
     342              :     return OMP_CLAUSE_DEFAULT_SHARED;
     343              : 
     344         7081 :   if (GFC_DECL_RESULT (decl) && ! DECL_HAS_VALUE_EXPR_P (decl))
     345              :     return OMP_CLAUSE_DEFAULT_SHARED;
     346              : 
     347              :   /* These are either array or derived parameters, or vtables.
     348              :      In the former cases, the OpenMP standard doesn't consider them to be
     349              :      variables at all (they can't be redefined), but they can nevertheless appear
     350              :      in parallel/task regions and for default(none) purposes treat them as shared.
     351              :      For vtables likely the same handling is desirable.  */
     352         5130 :   if (VAR_P (decl) && TREE_READONLY (decl)
     353         7060 :       && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
     354            3 :     return OMP_CLAUSE_DEFAULT_SHARED;
     355              : 
     356              :   return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
     357              : }
     358              : 
     359              : 
     360              : /* OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED unless OpenMP mapping attribute
     361              :    of DECL is predetermined.  */
     362              : 
     363              : enum omp_clause_defaultmap_kind
     364         4313 : gfc_omp_predetermined_mapping (tree decl)
     365              : {
     366         4313 :   if (DECL_ARTIFICIAL (decl)
     367         1036 :       && ! GFC_DECL_RESULT (decl)
     368         5343 :       && ! (DECL_LANG_SPECIFIC (decl)
     369           79 :             && GFC_DECL_SAVED_DESCRIPTOR (decl)))
     370              :     return OMP_CLAUSE_DEFAULTMAP_TO;
     371              : 
     372              :   /* Dummy procedures aren't considered variables by OpenMP, thus are
     373              :      disallowed in OpenMP clauses.  They are represented as PARM_DECLs
     374              :      in the middle-end, so return OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE here
     375              :      to avoid complaining about their uses with defaultmap(none).  */
     376         3332 :   if (TREE_CODE (decl) == PARM_DECL
     377         1824 :       && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
     378         3711 :       && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == FUNCTION_TYPE)
     379              :     return OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE;
     380              : 
     381              :   /* These are either array or derived parameters, or vtables.  */
     382         1508 :   if (VAR_P (decl) && TREE_READONLY (decl)
     383         3325 :       && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
     384            0 :     return OMP_CLAUSE_DEFAULTMAP_TO;
     385              : 
     386              :   return OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED;
     387              : }
     388              : 
     389              : 
     390              : /* Return decl that should be used when reporting DEFAULT(NONE)
     391              :    diagnostics.  */
     392              : 
     393              : tree
     394          128 : gfc_omp_report_decl (tree decl)
     395              : {
     396          128 :   if (DECL_ARTIFICIAL (decl)
     397            3 :       && DECL_LANG_SPECIFIC (decl)
     398          131 :       && GFC_DECL_SAVED_DESCRIPTOR (decl))
     399            3 :     return GFC_DECL_SAVED_DESCRIPTOR (decl);
     400              : 
     401              :   return decl;
     402              : }
     403              : 
     404              : /* Return true if TYPE has any allocatable components;
     405              :    if ptr_ok, the decl itself is permitted to have the POINTER attribute.
     406              :    if shallow_alloc_only, returns only true if any of the fields is an
     407              :    allocatable; called with true by gfc_omp_replace_alloc_by_to_mapping.  */
     408              : 
     409              : static bool
     410       123850 : gfc_has_alloc_comps (tree type, tree decl, bool ptr_ok,
     411              :                      bool shallow_alloc_only=false)
     412              : {
     413       123850 :   tree field, ftype;
     414              : 
     415       123850 :   if (POINTER_TYPE_P (type))
     416              :     {
     417         3471 :       if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
     418         3471 :           || (ptr_ok && GFC_DECL_GET_SCALAR_POINTER (decl)))
     419         2383 :         type = TREE_TYPE (type);
     420         1088 :       else if (GFC_DECL_GET_SCALAR_POINTER (decl))
     421              :         return false;
     422              :     }
     423              : 
     424       123717 :   if (!ptr_ok
     425        98865 :       && GFC_DESCRIPTOR_TYPE_P (type)
     426       127029 :       && (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER
     427         2909 :           || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT))
     428              :     return false;
     429              : 
     430       123311 :   if (GFC_DESCRIPTOR_TYPE_P (type) || GFC_ARRAY_TYPE_P (type))
     431        12928 :     type = gfc_get_element_type (type);
     432              : 
     433       123311 :   if (TREE_CODE (type) != RECORD_TYPE)
     434              :     return false;
     435              : 
     436        10381 :   for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
     437              :     {
     438         9194 :       ftype = TREE_TYPE (field);
     439         9194 :       if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
     440              :         return true;
     441         8626 :       if (GFC_DESCRIPTOR_TYPE_P (ftype)
     442         8626 :           && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
     443              :         return true;
     444         6153 :       if (!shallow_alloc_only
     445         6153 :           && gfc_has_alloc_comps (ftype, field, false))
     446              :         return true;
     447              :     }
     448              :   return false;
     449              : }
     450              : 
     451              : /* gfc_omp_replace_alloc_by_to_mapping is used with gfc_omp_deep_mapping... to
     452              :    handle the following:
     453              : 
     454              :    For map(alloc: dt), the array descriptors of allocatable components should
     455              :    be mapped as 'to'; this could be done by (A) adding 'map(to: dt%alloc_comp)'
     456              :    for each component (and avoiding to increment the reference count).
     457              :    Or (B) by just mapping all of 'dt' as 'to'.
     458              : 
     459              :    If 'dt' contains several allocatable components and not much other data,
     460              :    (A) is more efficient. If 'dt' contains a large const-size array, (A) will
     461              :    copy it to the device instead of only 'alloc'ating it.
     462              : 
     463              :    IMPLEMENTATION CHOICE: We do (A). It avoids the ref-count issue and it is
     464              :    expected that, for real-world code, derived types with allocatable
     465              :    components only have few other components and either no const-size arrays.
     466              :    This copying is done irrespectively whether the allocatables are allocated.
     467              : 
     468              :    If users wanted to save memory, they have to use 'map(alloc:dt%comp)' as
     469              :    also with 'map(alloc:dt)' all components get copied.
     470              : 
     471              :    For the copy to the device, only allocatable arrays are relevant as their
     472              :    the bounds are required; the pointer is set separately (GOMP_MAP_ATTACH)
     473              :    and the only setting required for scalars. However, when later copying out
     474              :    of the device, an unallocated allocatable must remain unallocated/NULL on
     475              :    the host; to achieve this we also must have it set to NULL on the device
     476              :    to avoid issues with uninitialized memory being copied back for the pointer
     477              :    address. If we could set the pointer to NULL, gfc_has_alloc_comps's
     478              :    shallow_alloc_only could be restricted to return true only for arrays.
     479              : 
     480              :    We only need to return true if there are allocatable-array components. */
     481              : 
     482              : static bool
     483           62 : gfc_omp_replace_alloc_by_to_mapping (tree type, tree decl, bool ptr_ok)
     484              : {
     485           18 :   return gfc_has_alloc_comps (type, decl, ptr_ok, true);
     486              : }
     487              : 
     488              : 
     489              : static bool
     490        67538 : gfc_is_polymorphic_nonptr (tree type)
     491              : {
     492        67538 :   if (POINTER_TYPE_P (type))
     493         3591 :     type = TREE_TYPE (type);
     494        67538 :   return GFC_CLASS_TYPE_P (type);
     495              : }
     496              : 
     497              : /* Return true if TYPE is a class container for a POINTER entity.  */
     498              : 
     499              : static bool
     500        41388 : gfc_is_class_pointer_type (tree type)
     501              : {
     502        41388 :   tree name;
     503        41388 :   const char *s;
     504              : 
     505        41388 :   if (POINTER_TYPE_P (type))
     506         3313 :     type = TREE_TYPE (type);
     507              : 
     508        41388 :   if (!GFC_CLASS_TYPE_P (type))
     509              :     return false;
     510              : 
     511           95 :   name = TYPE_NAME (type);
     512           95 :   if (name && TREE_CODE (name) == TYPE_DECL)
     513            0 :     name = DECL_NAME (name);
     514            0 :   if (!name)
     515              :     return false;
     516              : 
     517           95 :   s = IDENTIFIER_POINTER (name);
     518           95 :   return startswith (s, "__class_") && s[strlen (s) - 1] == 'p';
     519              : }
     520              : 
     521              : /* Return true if TYPE is unlimited polymorphic but not with pointer attribute;
     522              :    unlimited means also intrinsic types are handled and _len is used.  */
     523              : 
     524              : static bool
     525           77 : gfc_is_unlimited_polymorphic_nonptr (tree type)
     526              : {
     527           77 :   if (POINTER_TYPE_P (type))
     528            0 :     type = TREE_TYPE (type);
     529           77 :   if (!GFC_CLASS_TYPE_P (type))
     530              :     return false;
     531              : 
     532           77 :   tree field = TYPE_FIELDS (type); /* _data */
     533           77 :   gcc_assert (field);
     534           77 :   field = DECL_CHAIN (field); /* _vptr */
     535           77 :   gcc_assert (field);
     536           77 :   field = DECL_CHAIN (field);
     537           77 :   if (!field)
     538              :     return false;
     539           26 :   gcc_assert (strcmp ("_len", IDENTIFIER_POINTER (DECL_NAME (field))) == 0);
     540              :   return true;
     541              : }
     542              : 
     543              : /* Return true if the DECL is for an allocatable array or scalar.  */
     544              : 
     545              : bool
     546         4313 : gfc_omp_allocatable_p (tree decl)
     547              : {
     548         4313 :   if (!DECL_P (decl))
     549              :     return false;
     550              : 
     551         4313 :   if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl))
     552              :     return true;
     553              : 
     554         4088 :   tree type = TREE_TYPE (decl);
     555         4088 :   if (gfc_omp_privatize_by_reference (decl))
     556         1817 :     type = TREE_TYPE (type);
     557              : 
     558         4088 :   if (GFC_DESCRIPTOR_TYPE_P (type)
     559         4088 :       && GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE)
     560              :     return true;
     561              : 
     562              :   return false;
     563              : }
     564              : 
     565              : 
     566              : /* Return true if DECL in private clause needs
     567              :    OMP_CLAUSE_PRIVATE_OUTER_REF on the private clause.  */
     568              : bool
     569        14500 : gfc_omp_private_outer_ref (tree decl)
     570              : {
     571        14500 :   tree type = TREE_TYPE (decl);
     572              : 
     573        14500 :   if (gfc_omp_privatize_by_reference (decl))
     574          618 :     type = TREE_TYPE (type);
     575              : 
     576        14500 :   if (GFC_DESCRIPTOR_TYPE_P (type)
     577        14500 :       && GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE)
     578              :     return true;
     579              : 
     580        14371 :   if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl))
     581              :     return true;
     582              : 
     583        14285 :   if (gfc_has_alloc_comps (type, decl, false))
     584              :     return true;
     585              : 
     586              :   return false;
     587              : }
     588              : 
     589              : /* Callback for gfc_omp_unshare_expr.  */
     590              : 
     591              : static tree
     592        92489 : gfc_omp_unshare_expr_r (tree *tp, int *walk_subtrees, void *)
     593              : {
     594        92489 :   tree t = *tp;
     595        92489 :   enum tree_code code = TREE_CODE (t);
     596              : 
     597              :   /* Stop at types, decls, constants like copy_tree_r.  */
     598        92489 :   if (TREE_CODE_CLASS (code) == tcc_type
     599              :       || TREE_CODE_CLASS (code) == tcc_declaration
     600        92489 :       || TREE_CODE_CLASS (code) == tcc_constant
     601        61324 :       || code == BLOCK)
     602        31165 :     *walk_subtrees = 0;
     603        61324 :   else if (handled_component_p (t)
     604        46362 :            || TREE_CODE (t) == MEM_REF)
     605              :     {
     606        15022 :       *tp = unshare_expr (t);
     607        15022 :       *walk_subtrees = 0;
     608              :     }
     609              : 
     610        92489 :   return NULL_TREE;
     611              : }
     612              : 
     613              : /* Unshare in expr anything that the FE which normally doesn't
     614              :    care much about tree sharing (because during gimplification
     615              :    everything is unshared) could cause problems with tree sharing
     616              :    at omp-low.cc time.  */
     617              : 
     618              : static tree
     619         5078 : gfc_omp_unshare_expr (tree expr)
     620              : {
     621         5078 :   walk_tree (&expr, gfc_omp_unshare_expr_r, NULL, NULL);
     622         5078 :   return expr;
     623              : }
     624              : 
     625              : enum walk_alloc_comps
     626              : {
     627              :   WALK_ALLOC_COMPS_DTOR,
     628              :   WALK_ALLOC_COMPS_DEFAULT_CTOR,
     629              :   WALK_ALLOC_COMPS_COPY_CTOR
     630              : };
     631              : 
     632              : /* Handle allocatable components in OpenMP clauses.  */
     633              : 
     634              : static tree
     635         2803 : gfc_walk_alloc_comps (tree decl, tree dest, tree var,
     636              :                       enum walk_alloc_comps kind)
     637              : {
     638         2803 :   stmtblock_t block, tmpblock;
     639         2803 :   tree type = TREE_TYPE (decl), then_b, tem, field;
     640         2803 :   gfc_init_block (&block);
     641              : 
     642         2803 :   if (GFC_ARRAY_TYPE_P (type) || GFC_DESCRIPTOR_TYPE_P (type))
     643              :     {
     644         1092 :       if (GFC_DESCRIPTOR_TYPE_P (type))
     645              :         {
     646          548 :           gfc_init_block (&tmpblock);
     647         1644 :           tem = gfc_full_array_size (&tmpblock, decl,
     648          548 :                                      GFC_TYPE_ARRAY_RANK (type));
     649          548 :           then_b = gfc_finish_block (&tmpblock);
     650          548 :           gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (then_b));
     651          548 :           tem = gfc_omp_unshare_expr (tem);
     652          548 :           tem = fold_build2_loc (input_location, MINUS_EXPR,
     653              :                                  gfc_array_index_type, tem,
     654              :                                  gfc_index_one_node);
     655              :         }
     656              :       else
     657              :         {
     658          544 :           bool compute_nelts = false;
     659          544 :           if (!TYPE_DOMAIN (type)
     660          544 :               || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE
     661          544 :               || TYPE_MIN_VALUE (TYPE_DOMAIN (type)) == error_mark_node
     662         1088 :               || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == error_mark_node)
     663              :             compute_nelts = true;
     664          544 :           else if (VAR_P (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
     665              :             {
     666           80 :               tree a = DECL_ATTRIBUTES (TYPE_MAX_VALUE (TYPE_DOMAIN (type)));
     667           80 :               if (lookup_attribute ("omp dummy var", a))
     668              :                 compute_nelts = true;
     669              :             }
     670              :           if (compute_nelts)
     671              :             {
     672           80 :               tem = fold_build2 (EXACT_DIV_EXPR, sizetype,
     673              :                                  TYPE_SIZE_UNIT (type),
     674              :                                  TYPE_SIZE_UNIT (TREE_TYPE (type)));
     675           80 :               tem = size_binop (MINUS_EXPR, tem, size_one_node);
     676              :             }
     677              :           else
     678          464 :             tem = array_type_nelts_minus_one (type);
     679          544 :           tem = fold_convert (gfc_array_index_type, tem);
     680              :         }
     681              : 
     682         1092 :       tree nelems = gfc_evaluate_now (tem, &block);
     683         1092 :       tree index = gfc_create_var (gfc_array_index_type, "S");
     684              : 
     685         1092 :       gfc_init_block (&tmpblock);
     686         1092 :       tem = gfc_conv_array_data (decl);
     687         1092 :       tree declvar = build_fold_indirect_ref_loc (input_location, tem);
     688         1092 :       tree declvref = gfc_build_array_ref (declvar, index, NULL);
     689         1092 :       tree destvar, destvref = NULL_TREE;
     690         1092 :       if (dest)
     691              :         {
     692          546 :           tem = gfc_conv_array_data (dest);
     693          546 :           destvar = build_fold_indirect_ref_loc (input_location, tem);
     694          546 :           destvref = gfc_build_array_ref (destvar, index, NULL);
     695              :         }
     696         1092 :       gfc_add_expr_to_block (&tmpblock,
     697              :                              gfc_walk_alloc_comps (declvref, destvref,
     698              :                                                    var, kind));
     699              : 
     700         1092 :       gfc_loopinfo loop;
     701         1092 :       gfc_init_loopinfo (&loop);
     702         1092 :       loop.dimen = 1;
     703         1092 :       loop.from[0] = gfc_index_zero_node;
     704         1092 :       loop.loopvar[0] = index;
     705         1092 :       loop.to[0] = nelems;
     706         1092 :       gfc_trans_scalarizing_loops (&loop, &tmpblock);
     707         1092 :       gfc_add_block_to_block (&block, &loop.pre);
     708         1092 :       return gfc_finish_block (&block);
     709              :     }
     710         1711 :   else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (var))
     711              :     {
     712          536 :       decl = build_fold_indirect_ref_loc (input_location, decl);
     713          536 :       if (dest)
     714          268 :         dest = build_fold_indirect_ref_loc (input_location, dest);
     715          536 :       type = TREE_TYPE (decl);
     716              :     }
     717              : 
     718         1711 :   gcc_assert (TREE_CODE (type) == RECORD_TYPE);
     719        11494 :   for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
     720              :     {
     721         9783 :       tree ftype = TREE_TYPE (field);
     722         9783 :       tree declf, destf = NULL_TREE;
     723         9783 :       bool has_alloc_comps = gfc_has_alloc_comps (ftype, field, false);
     724         9783 :       if ((!GFC_DESCRIPTOR_TYPE_P (ftype)
     725         1710 :            || GFC_TYPE_ARRAY_AKIND (ftype) != GFC_ARRAY_ALLOCATABLE)
     726         8073 :           && !GFC_DECL_GET_SCALAR_ALLOCATABLE (field)
     727        16159 :           && !has_alloc_comps)
     728         5952 :         continue;
     729         3831 :       declf = fold_build3_loc (input_location, COMPONENT_REF, ftype,
     730              :                                decl, field, NULL_TREE);
     731         3831 :       if (dest)
     732         1916 :         destf = fold_build3_loc (input_location, COMPONENT_REF, ftype,
     733              :                                  dest, field, NULL_TREE);
     734              : 
     735         3831 :       tem = NULL_TREE;
     736         3831 :       switch (kind)
     737              :         {
     738              :         case WALK_ALLOC_COMPS_DTOR:
     739              :           break;
     740          962 :         case WALK_ALLOC_COMPS_DEFAULT_CTOR:
     741          962 :           if (GFC_DESCRIPTOR_TYPE_P (ftype)
     742          962 :               && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
     743              :             {
     744          431 :               gfc_add_modify (&block, unshare_expr (destf),
     745              :                               unshare_expr (declf));
     746          431 :               tem = gfc_duplicate_allocatable_nocopy
     747          431 :                                         (destf, declf, ftype,
     748          431 :                                          GFC_TYPE_ARRAY_RANK (ftype));
     749              :             }
     750          531 :           else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
     751          425 :             tem = gfc_duplicate_allocatable_nocopy (destf, declf, ftype, 0);
     752              :           break;
     753          954 :         case WALK_ALLOC_COMPS_COPY_CTOR:
     754          954 :           if (GFC_DESCRIPTOR_TYPE_P (ftype)
     755          954 :               && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
     756          848 :             tem = gfc_duplicate_allocatable (destf, declf, ftype,
     757          424 :                                              GFC_TYPE_ARRAY_RANK (ftype),
     758              :                                              NULL_TREE);
     759          530 :           else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
     760          424 :             tem = gfc_duplicate_allocatable (destf, declf, ftype, 0,
     761              :                                              NULL_TREE);
     762              :           break;
     763              :         }
     764         1704 :       if (tem)
     765         1704 :         gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (tem));
     766         3831 :       if (has_alloc_comps)
     767              :         {
     768         1272 :           gfc_init_block (&tmpblock);
     769         1272 :           gfc_add_expr_to_block (&tmpblock,
     770              :                                  gfc_walk_alloc_comps (declf, destf,
     771              :                                                        field, kind));
     772         1272 :           then_b = gfc_finish_block (&tmpblock);
     773         1272 :           if (GFC_DESCRIPTOR_TYPE_P (ftype)
     774         1272 :               && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
     775          424 :             tem = gfc_conv_descriptor_data_get (unshare_expr (declf));
     776          848 :           else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
     777          424 :             tem = unshare_expr (declf);
     778              :           else
     779              :             tem = NULL_TREE;
     780          848 :           if (tem)
     781              :             {
     782          848 :               tem = fold_convert (pvoid_type_node, tem);
     783          848 :               tem = fold_build2_loc (input_location, NE_EXPR,
     784              :                                      logical_type_node, tem,
     785              :                                      null_pointer_node);
     786          848 :               then_b = build3_loc (input_location, COND_EXPR, void_type_node,
     787              :                                    tem, then_b,
     788              :                                    build_empty_stmt (input_location));
     789              :             }
     790         1272 :           gfc_add_expr_to_block (&block, then_b);
     791              :         }
     792         3831 :       if (kind == WALK_ALLOC_COMPS_DTOR)
     793              :         {
     794         1915 :           if (GFC_DESCRIPTOR_TYPE_P (ftype)
     795         1915 :               && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
     796              :             {
     797          855 :               tem = gfc_conv_descriptor_data_get (unshare_expr (declf));
     798          855 :               tem = gfc_deallocate_with_status (tem, NULL_TREE, NULL_TREE,
     799              :                                                 NULL_TREE, NULL_TREE, true,
     800              :                                                 NULL,
     801              :                                                 GFC_CAF_COARRAY_NOCOARRAY);
     802          855 :               gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (tem));
     803              :             }
     804         1060 :           else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
     805              :             {
     806          848 :               tem = gfc_call_free (unshare_expr (declf));
     807          848 :               gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (tem));
     808              :             }
     809              :         }
     810              :     }
     811              : 
     812         1711 :   return gfc_finish_block (&block);
     813              : }
     814              : 
     815              : /* Return code to initialize DECL with its default constructor, or
     816              :    NULL if there's nothing to do.  */
     817              : 
     818              : tree
     819        20426 : gfc_omp_clause_default_ctor (tree clause, tree decl, tree outer)
     820              : {
     821        20426 :   tree type = TREE_TYPE (decl), size, ptr, cond, then_b, else_b;
     822        20426 :   stmtblock_t block, cond_block;
     823              : 
     824        20426 :   switch (OMP_CLAUSE_CODE (clause))
     825              :     {
     826              :     case OMP_CLAUSE__LOOPTEMP_:
     827              :     case OMP_CLAUSE__REDUCTEMP_:
     828              :     case OMP_CLAUSE__CONDTEMP_:
     829              :     case OMP_CLAUSE__SCANTEMP_:
     830              :       return NULL;
     831        20399 :     case OMP_CLAUSE_PRIVATE:
     832        20399 :     case OMP_CLAUSE_LASTPRIVATE:
     833        20399 :     case OMP_CLAUSE_LINEAR:
     834        20399 :     case OMP_CLAUSE_REDUCTION:
     835        20399 :     case OMP_CLAUSE_IN_REDUCTION:
     836        20399 :     case OMP_CLAUSE_TASK_REDUCTION:
     837        20399 :       break;
     838            0 :     default:
     839            0 :       gcc_unreachable ();
     840              :     }
     841              : 
     842        20399 :   if ((! GFC_DESCRIPTOR_TYPE_P (type)
     843          265 :        || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
     844        20418 :       && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))
     845           86 :           || !POINTER_TYPE_P (type)))
     846              :     {
     847        20067 :       if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause), false))
     848              :         {
     849           52 :           gcc_assert (outer);
     850           52 :           gfc_start_block (&block);
     851          104 :           tree tem = gfc_walk_alloc_comps (outer, decl,
     852           52 :                                            OMP_CLAUSE_DECL (clause),
     853              :                                            WALK_ALLOC_COMPS_DEFAULT_CTOR);
     854           52 :           gfc_add_expr_to_block (&block, tem);
     855           52 :           return gfc_finish_block (&block);
     856              :         }
     857              :       return NULL_TREE;
     858              :     }
     859              : 
     860          332 :   gcc_assert (outer != NULL_TREE
     861              :               || (!GFC_DESCRIPTOR_TYPE_P (type)
     862              :                   && !gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause),
     863              :                                            false)));
     864              : 
     865              :   /* Allocatable arrays and scalars in PRIVATE clauses need to be set to
     866              :      "not currently allocated" allocation status if outer
     867              :      array is "not currently allocated", otherwise should be allocated.  */
     868          332 :   gfc_start_block (&block);
     869              : 
     870          332 :   gfc_init_block (&cond_block);
     871              : 
     872          332 :   if (GFC_DESCRIPTOR_TYPE_P (type))
     873              :     {
     874          246 :       gfc_add_modify (&cond_block, decl, outer);
     875          246 :       tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
     876          246 :       size = gfc_conv_descriptor_ubound_get (decl, rank);
     877          246 :       size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
     878              :                               size,
     879              :                               gfc_conv_descriptor_lbound_get (decl, rank));
     880          246 :       size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
     881              :                               size, gfc_index_one_node);
     882          246 :       if (GFC_TYPE_ARRAY_RANK (type) > 1)
     883          130 :         size = fold_build2_loc (input_location, MULT_EXPR,
     884              :                                 gfc_array_index_type, size,
     885              :                                 gfc_conv_descriptor_stride_get (decl, rank));
     886          246 :       tree esize = fold_convert (gfc_array_index_type,
     887              :                                  TYPE_SIZE_UNIT (gfc_get_element_type (type)));
     888          246 :       size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
     889              :                               size, esize);
     890          246 :       size = unshare_expr (size);
     891          246 :       size = gfc_evaluate_now (fold_convert (size_type_node, size),
     892              :                                &cond_block);
     893              :     }
     894              :   else
     895           86 :     size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
     896          332 :   ptr = gfc_create_var (pvoid_type_node, NULL);
     897          332 :   gfc_allocate_using_malloc (&cond_block, ptr, size, NULL_TREE);
     898          332 :   if (GFC_DESCRIPTOR_TYPE_P (type))
     899          246 :     gfc_conv_descriptor_data_set (&cond_block, unshare_expr (decl), ptr);
     900              :   else
     901           86 :     gfc_add_modify (&cond_block, unshare_expr (decl),
     902           86 :                     fold_convert (TREE_TYPE (decl), ptr));
     903          332 :   if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause), false))
     904              :     {
     905          124 :       tree tem = gfc_walk_alloc_comps (outer, decl,
     906           62 :                                        OMP_CLAUSE_DECL (clause),
     907              :                                        WALK_ALLOC_COMPS_DEFAULT_CTOR);
     908           62 :       gfc_add_expr_to_block (&cond_block, tem);
     909              :     }
     910          332 :   then_b = gfc_finish_block (&cond_block);
     911              : 
     912              :   /* Reduction clause requires allocated ALLOCATABLE.  */
     913          332 :   if (OMP_CLAUSE_CODE (clause) != OMP_CLAUSE_REDUCTION
     914          187 :       && OMP_CLAUSE_CODE (clause) != OMP_CLAUSE_IN_REDUCTION
     915          519 :       && OMP_CLAUSE_CODE (clause) != OMP_CLAUSE_TASK_REDUCTION)
     916              :     {
     917          187 :       gfc_init_block (&cond_block);
     918          187 :       if (GFC_DESCRIPTOR_TYPE_P (type))
     919          126 :         gfc_conv_descriptor_data_set (&cond_block, unshare_expr (decl),
     920              :                                       null_pointer_node);
     921              :       else
     922           61 :         gfc_add_modify (&cond_block, unshare_expr (decl),
     923           61 :                         build_zero_cst (TREE_TYPE (decl)));
     924          187 :       else_b = gfc_finish_block (&cond_block);
     925              : 
     926          187 :       tree tem = fold_convert (pvoid_type_node,
     927              :                                GFC_DESCRIPTOR_TYPE_P (type)
     928              :                                ? gfc_conv_descriptor_data_get (outer) : outer);
     929          187 :       tem = unshare_expr (tem);
     930          187 :       cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
     931              :                               tem, null_pointer_node);
     932          187 :       gfc_add_expr_to_block (&block,
     933              :                              build3_loc (input_location, COND_EXPR,
     934              :                                          void_type_node, cond, then_b,
     935              :                                          else_b));
     936              :       /* Avoid -W*uninitialized warnings.  */
     937          187 :       if (DECL_P (decl))
     938          148 :         suppress_warning (decl, OPT_Wuninitialized);
     939              :     }
     940              :   else
     941          145 :     gfc_add_expr_to_block (&block, then_b);
     942              : 
     943          332 :   return gfc_finish_block (&block);
     944              : }
     945              : 
     946              : /* Build and return code for a copy constructor from SRC to DEST.  */
     947              : 
     948              : tree
     949         9311 : gfc_omp_clause_copy_ctor (tree clause, tree dest, tree src)
     950              : {
     951         9311 :   tree type = TREE_TYPE (dest), ptr, size, call;
     952         9311 :   tree decl_type = TREE_TYPE (OMP_CLAUSE_DECL (clause));
     953         9311 :   tree orig_decl = OMP_CLAUSE_DECL (clause);
     954         9311 :   tree cond, then_b, else_b;
     955         9311 :   stmtblock_t block, cond_block;
     956              : 
     957         9311 :   gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_FIRSTPRIVATE
     958              :               || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR);
     959              : 
     960         9311 :   if (DECL_ARTIFICIAL (orig_decl)
     961         6195 :       && DECL_LANG_SPECIFIC (orig_decl)
     962         9500 :       && GFC_DECL_SAVED_DESCRIPTOR (orig_decl))
     963              :     {
     964          173 :       orig_decl = GFC_DECL_SAVED_DESCRIPTOR (orig_decl);
     965          173 :       decl_type = TREE_TYPE (orig_decl);
     966              :     }
     967              : 
     968              :   /* Privatize pointer association only; cf. gfc_omp_predetermined_sharing.
     969              :      This includes scalar class pointers, whose tree type is still the class
     970              :      record even though the Fortran entity has POINTER semantics.  */
     971         9311 :   if (DECL_P (orig_decl)
     972         9311 :       && (GFC_DECL_ASSOCIATE_VAR_P (orig_decl)
     973         9284 :           || GFC_DECL_GET_SCALAR_POINTER (orig_decl)
     974         9258 :           || gfc_is_class_pointer_type (decl_type)))
     975           59 :     return build2 (MODIFY_EXPR, TREE_TYPE (dest), dest, src);
     976              : 
     977         9252 :   if (gfc_is_polymorphic_nonptr (decl_type))
     978              :     {
     979           40 :       if (POINTER_TYPE_P (decl_type))
     980           27 :         decl_type = TREE_TYPE (decl_type);
     981           40 :       decl_type = TREE_TYPE (TYPE_FIELDS (decl_type));
     982           40 :       if (GFC_DESCRIPTOR_TYPE_P (decl_type) || GFC_ARRAY_TYPE_P (decl_type))
     983            4 :         fatal_error (input_location,
     984              :                      "Sorry, polymorphic arrays not yet supported for "
     985              :                      "firstprivate");
     986           36 :       tree src_len;
     987           36 :       tree nelems = build_int_cst (size_type_node, 1);  /* Scalar.  */
     988           36 :       tree src_data = gfc_class_data_get (unshare_expr (src));
     989           36 :       tree dest_data = gfc_class_data_get (unshare_expr (dest));
     990           36 :       bool unlimited = gfc_is_unlimited_polymorphic_nonptr (type);
     991              : 
     992           36 :       gfc_start_block (&block);
     993           36 :       gfc_add_modify (&block, gfc_class_vptr_get (dest),
     994              :                       gfc_class_vptr_get (src));
     995           36 :       gfc_init_block (&cond_block);
     996              : 
     997           36 :       if (unlimited)
     998              :         {
     999           24 :           src_len = gfc_class_len_get (src);
    1000           24 :           gfc_add_modify (&cond_block, gfc_class_len_get (unshare_expr (dest)), src_len);
    1001              :         }
    1002              : 
    1003              :       /* Use: size = class._vtab._size * (class._len > 0 ? class._len : 1).  */
    1004           36 :       size = fold_convert (size_type_node, gfc_class_vtab_size_get (src));
    1005           36 :       if (unlimited)
    1006              :         {
    1007           24 :           cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
    1008              :                                   unshare_expr (src_len),
    1009           24 :                                   build_zero_cst (TREE_TYPE (src_len)));
    1010           24 :           cond = build3_loc (input_location, COND_EXPR, size_type_node, cond,
    1011              :                              fold_convert (size_type_node,
    1012              :                                            unshare_expr (src_len)),
    1013              :                              build_int_cst (size_type_node, 1));
    1014           24 :           size = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
    1015              :                                   size, cond);
    1016              :         }
    1017              : 
    1018              :       /* Malloc memory + call class->_vpt->_copy.  */
    1019           36 :       call = builtin_decl_explicit (BUILT_IN_MALLOC);
    1020           36 :       call = build_call_expr_loc (input_location, call, 1, size);
    1021           36 :       gfc_add_modify (&cond_block, dest_data,
    1022           36 :                       fold_convert (TREE_TYPE (dest_data), call));
    1023           36 :       gfc_add_expr_to_block (&cond_block,
    1024              :                              gfc_copy_class_to_class (src, dest, nelems,
    1025              :                                                       unlimited));
    1026              : 
    1027           36 :       gcc_assert (TREE_CODE (dest_data) == COMPONENT_REF);
    1028           36 :       if (!GFC_DECL_GET_SCALAR_ALLOCATABLE (TREE_OPERAND (dest_data, 1)))
    1029              :         {
    1030           12 :           gfc_add_block_to_block (&block, &cond_block);
    1031              :         }
    1032              :       else
    1033              :         {
    1034              :           /* Create: if (class._data != 0) <cond_block> else class._data = NULL; */
    1035           24 :           cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
    1036              :                                   src_data, null_pointer_node);
    1037           24 :           gfc_add_expr_to_block (&block, build3_loc (input_location, COND_EXPR,
    1038              :                                  void_type_node, cond,
    1039              :                                  gfc_finish_block (&cond_block),
    1040              :                                  fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
    1041              :                                  unshare_expr (dest_data), null_pointer_node)));
    1042              :         }
    1043           36 :       return gfc_finish_block (&block);
    1044              :     }
    1045              : 
    1046         9212 :   if ((! GFC_DESCRIPTOR_TYPE_P (type)
    1047          151 :        || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
    1048         9242 :       && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))
    1049           77 :           || !POINTER_TYPE_P (type)))
    1050              :     {
    1051         9016 :       if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause), false))
    1052              :         {
    1053           20 :           gfc_start_block (&block);
    1054           20 :           gfc_add_modify (&block, dest, src);
    1055           20 :           tree tem = gfc_walk_alloc_comps (src, dest, OMP_CLAUSE_DECL (clause),
    1056              :                                            WALK_ALLOC_COMPS_COPY_CTOR);
    1057           20 :           gfc_add_expr_to_block (&block, tem);
    1058           20 :           return gfc_finish_block (&block);
    1059              :         }
    1060              :       else
    1061         8996 :         return build2_v (MODIFY_EXPR, dest, src);
    1062              :     }
    1063              : 
    1064              :   /* Allocatable arrays in FIRSTPRIVATE clauses need to be allocated
    1065              :      and copied from SRC.  */
    1066          196 :   gfc_start_block (&block);
    1067              : 
    1068          196 :   gfc_init_block (&cond_block);
    1069              : 
    1070          196 :   gfc_add_modify (&cond_block, dest, fold_convert (TREE_TYPE (dest), src));
    1071          196 :   if (GFC_DESCRIPTOR_TYPE_P (type))
    1072              :     {
    1073          121 :       tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
    1074          121 :       size = gfc_conv_descriptor_ubound_get (dest, rank);
    1075          121 :       size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
    1076              :                               size,
    1077              :                               gfc_conv_descriptor_lbound_get (dest, rank));
    1078          121 :       size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
    1079              :                               size, gfc_index_one_node);
    1080          121 :       if (GFC_TYPE_ARRAY_RANK (type) > 1)
    1081           42 :         size = fold_build2_loc (input_location, MULT_EXPR,
    1082              :                                 gfc_array_index_type, size,
    1083              :                                 gfc_conv_descriptor_stride_get (dest, rank));
    1084          121 :       tree esize = fold_convert (gfc_array_index_type,
    1085              :                                  TYPE_SIZE_UNIT (gfc_get_element_type (type)));
    1086          121 :       size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
    1087              :                               size, esize);
    1088          121 :       size = unshare_expr (size);
    1089          121 :       size = gfc_evaluate_now (fold_convert (size_type_node, size),
    1090              :                                &cond_block);
    1091              :     }
    1092              :   else
    1093           75 :     size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
    1094          196 :   ptr = gfc_create_var (pvoid_type_node, NULL);
    1095          196 :   gfc_allocate_using_malloc (&cond_block, ptr, size, NULL_TREE);
    1096          196 :   if (GFC_DESCRIPTOR_TYPE_P (type))
    1097          121 :     gfc_conv_descriptor_data_set (&cond_block, unshare_expr (dest), ptr);
    1098              :   else
    1099           75 :     gfc_add_modify (&cond_block, unshare_expr (dest),
    1100           75 :                     fold_convert (TREE_TYPE (dest), ptr));
    1101              : 
    1102          196 :   tree srcptr = GFC_DESCRIPTOR_TYPE_P (type)
    1103          196 :                 ? gfc_conv_descriptor_data_get (src) : src;
    1104          196 :   srcptr = unshare_expr (srcptr);
    1105          196 :   srcptr = fold_convert (pvoid_type_node, srcptr);
    1106          196 :   call = build_call_expr_loc (input_location,
    1107              :                               builtin_decl_explicit (BUILT_IN_MEMCPY), 3, ptr,
    1108              :                               srcptr, size);
    1109          196 :   gfc_add_expr_to_block (&cond_block, fold_convert (void_type_node, call));
    1110          196 :   if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause), false))
    1111              :     {
    1112           48 :       tree tem = gfc_walk_alloc_comps (src, dest,
    1113           24 :                                        OMP_CLAUSE_DECL (clause),
    1114              :                                        WALK_ALLOC_COMPS_COPY_CTOR);
    1115           24 :       gfc_add_expr_to_block (&cond_block, tem);
    1116              :     }
    1117          196 :   then_b = gfc_finish_block (&cond_block);
    1118              : 
    1119          196 :   gfc_init_block (&cond_block);
    1120          196 :   if (GFC_DESCRIPTOR_TYPE_P (type))
    1121          121 :     gfc_conv_descriptor_data_set (&cond_block, unshare_expr (dest),
    1122              :                                   null_pointer_node);
    1123              :   else
    1124           75 :     gfc_add_modify (&cond_block, unshare_expr (dest),
    1125           75 :                     build_zero_cst (TREE_TYPE (dest)));
    1126          196 :   else_b = gfc_finish_block (&cond_block);
    1127              : 
    1128          196 :   cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
    1129              :                           unshare_expr (srcptr), null_pointer_node);
    1130          196 :   gfc_add_expr_to_block (&block,
    1131              :                          build3_loc (input_location, COND_EXPR,
    1132              :                                      void_type_node, cond, then_b, else_b));
    1133              :   /* Avoid -W*uninitialized warnings.  */
    1134          196 :   if (DECL_P (dest))
    1135          127 :     suppress_warning (dest, OPT_Wuninitialized);
    1136              : 
    1137          196 :   return gfc_finish_block (&block);
    1138              : }
    1139              : 
    1140              : /* Similarly, except use an intrinsic or pointer assignment operator
    1141              :    instead.  */
    1142              : 
    1143              : tree
    1144         6355 : gfc_omp_clause_assign_op (tree clause, tree dest, tree src)
    1145              : {
    1146         6355 :   tree type = TREE_TYPE (dest), ptr, size, call, nonalloc;
    1147         6355 :   tree cond, then_b, else_b;
    1148         6355 :   stmtblock_t block, cond_block, cond_block2, inner_block;
    1149              : 
    1150         6355 :   if ((! GFC_DESCRIPTOR_TYPE_P (type)
    1151          236 :        || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
    1152        12505 :       && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))
    1153          136 :           || !POINTER_TYPE_P (type)))
    1154              :     {
    1155         6014 :       if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause), false))
    1156              :         {
    1157           30 :           gfc_start_block (&block);
    1158              :           /* First dealloc any allocatable components in DEST.  */
    1159           60 :           tree tem = gfc_walk_alloc_comps (dest, NULL_TREE,
    1160           30 :                                            OMP_CLAUSE_DECL (clause),
    1161              :                                            WALK_ALLOC_COMPS_DTOR);
    1162           30 :           gfc_add_expr_to_block (&block, tem);
    1163              :           /* Then copy over toplevel data.  */
    1164           30 :           gfc_add_modify (&block, dest, src);
    1165              :           /* Finally allocate any allocatable components and copy.  */
    1166           30 :           tem = gfc_walk_alloc_comps (src, dest, OMP_CLAUSE_DECL (clause),
    1167              :                                            WALK_ALLOC_COMPS_COPY_CTOR);
    1168           30 :           gfc_add_expr_to_block (&block, tem);
    1169           30 :           return gfc_finish_block (&block);
    1170              :         }
    1171              :       else
    1172         5984 :         return build2_v (MODIFY_EXPR, dest, src);
    1173              :     }
    1174              : 
    1175          341 :   gfc_start_block (&block);
    1176              : 
    1177          341 :   if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause), false))
    1178              :     {
    1179           32 :       then_b = gfc_walk_alloc_comps (dest, NULL_TREE, OMP_CLAUSE_DECL (clause),
    1180              :                                      WALK_ALLOC_COMPS_DTOR);
    1181           32 :       tree tem = fold_convert (pvoid_type_node,
    1182              :                                GFC_DESCRIPTOR_TYPE_P (type)
    1183              :                                ? gfc_conv_descriptor_data_get (dest) : dest);
    1184           32 :       tem = unshare_expr (tem);
    1185           32 :       cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
    1186              :                               tem, null_pointer_node);
    1187           32 :       tem = build3_loc (input_location, COND_EXPR, void_type_node, cond,
    1188              :                         then_b, build_empty_stmt (input_location));
    1189           32 :       gfc_add_expr_to_block (&block, tem);
    1190              :     }
    1191              : 
    1192          341 :   gfc_init_block (&cond_block);
    1193              : 
    1194          341 :   if (GFC_DESCRIPTOR_TYPE_P (type))
    1195              :     {
    1196          205 :       tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
    1197          205 :       size = gfc_conv_descriptor_ubound_get (src, rank);
    1198          205 :       size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
    1199              :                               size,
    1200              :                               gfc_conv_descriptor_lbound_get (src, rank));
    1201          205 :       size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
    1202              :                               size, gfc_index_one_node);
    1203          205 :       if (GFC_TYPE_ARRAY_RANK (type) > 1)
    1204           88 :         size = fold_build2_loc (input_location, MULT_EXPR,
    1205              :                                 gfc_array_index_type, size,
    1206              :                                 gfc_conv_descriptor_stride_get (src, rank));
    1207          205 :       tree esize = fold_convert (gfc_array_index_type,
    1208              :                                  TYPE_SIZE_UNIT (gfc_get_element_type (type)));
    1209          205 :       size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
    1210              :                               size, esize);
    1211          205 :       size = unshare_expr (size);
    1212          205 :       size = gfc_evaluate_now (fold_convert (size_type_node, size),
    1213              :                                &cond_block);
    1214              :     }
    1215              :   else
    1216          136 :     size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
    1217          341 :   ptr = gfc_create_var (pvoid_type_node, NULL);
    1218              : 
    1219          341 :   tree destptr = GFC_DESCRIPTOR_TYPE_P (type)
    1220          341 :                  ? gfc_conv_descriptor_data_get (dest) : dest;
    1221          341 :   destptr = unshare_expr (destptr);
    1222          341 :   destptr = fold_convert (pvoid_type_node, destptr);
    1223          341 :   gfc_add_modify (&cond_block, ptr, destptr);
    1224              : 
    1225          341 :   nonalloc = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
    1226              :                               destptr, null_pointer_node);
    1227          341 :   cond = nonalloc;
    1228          341 :   if (GFC_DESCRIPTOR_TYPE_P (type))
    1229              :     {
    1230              :       int i;
    1231          498 :       for (i = 0; i < GFC_TYPE_ARRAY_RANK (type); i++)
    1232              :         {
    1233          293 :           tree rank = gfc_rank_cst[i];
    1234          293 :           tree tem = gfc_conv_descriptor_ubound_get (src, rank);
    1235          293 :           tem = fold_build2_loc (input_location, MINUS_EXPR,
    1236              :                                  gfc_array_index_type, tem,
    1237              :                                  gfc_conv_descriptor_lbound_get (src, rank));
    1238          293 :           tem = fold_build2_loc (input_location, PLUS_EXPR,
    1239              :                                  gfc_array_index_type, tem,
    1240              :                                  gfc_conv_descriptor_lbound_get (dest, rank));
    1241          293 :           tem = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
    1242              :                                  tem, gfc_conv_descriptor_ubound_get (dest,
    1243              :                                                                       rank));
    1244          293 :           cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
    1245              :                                   logical_type_node, cond, tem);
    1246              :         }
    1247              :     }
    1248              : 
    1249          341 :   gfc_init_block (&cond_block2);
    1250              : 
    1251          341 :   if (GFC_DESCRIPTOR_TYPE_P (type))
    1252              :     {
    1253          205 :       gfc_init_block (&inner_block);
    1254          205 :       gfc_allocate_using_malloc (&inner_block, ptr, size, NULL_TREE);
    1255          205 :       then_b = gfc_finish_block (&inner_block);
    1256              : 
    1257          205 :       gfc_init_block (&inner_block);
    1258          205 :       gfc_add_modify (&inner_block, ptr,
    1259              :                       gfc_call_realloc (&inner_block, ptr, size));
    1260          205 :       else_b = gfc_finish_block (&inner_block);
    1261              : 
    1262          205 :       gfc_add_expr_to_block (&cond_block2,
    1263              :                              build3_loc (input_location, COND_EXPR,
    1264              :                                          void_type_node,
    1265              :                                          unshare_expr (nonalloc),
    1266              :                                          then_b, else_b));
    1267          205 :       gfc_add_modify (&cond_block2, dest, src);
    1268          205 :       gfc_conv_descriptor_data_set (&cond_block2, unshare_expr (dest), ptr);
    1269              :     }
    1270              :   else
    1271              :     {
    1272          136 :       gfc_allocate_using_malloc (&cond_block2, ptr, size, NULL_TREE);
    1273          136 :       gfc_add_modify (&cond_block2, unshare_expr (dest),
    1274              :                       fold_convert (type, ptr));
    1275              :     }
    1276          341 :   then_b = gfc_finish_block (&cond_block2);
    1277          341 :   else_b = build_empty_stmt (input_location);
    1278              : 
    1279          341 :   gfc_add_expr_to_block (&cond_block,
    1280              :                          build3_loc (input_location, COND_EXPR,
    1281              :                                      void_type_node, unshare_expr (cond),
    1282              :                                      then_b, else_b));
    1283              : 
    1284          341 :   tree srcptr = GFC_DESCRIPTOR_TYPE_P (type)
    1285          341 :                 ? gfc_conv_descriptor_data_get (src) : src;
    1286          341 :   srcptr = unshare_expr (srcptr);
    1287          341 :   srcptr = fold_convert (pvoid_type_node, srcptr);
    1288          341 :   call = build_call_expr_loc (input_location,
    1289              :                               builtin_decl_explicit (BUILT_IN_MEMCPY), 3, ptr,
    1290              :                               srcptr, size);
    1291          341 :   gfc_add_expr_to_block (&cond_block, fold_convert (void_type_node, call));
    1292          341 :   if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause), false))
    1293              :     {
    1294           64 :       tree tem = gfc_walk_alloc_comps (src, dest,
    1295           32 :                                        OMP_CLAUSE_DECL (clause),
    1296              :                                        WALK_ALLOC_COMPS_COPY_CTOR);
    1297           32 :       gfc_add_expr_to_block (&cond_block, tem);
    1298              :     }
    1299          341 :   then_b = gfc_finish_block (&cond_block);
    1300              : 
    1301          341 :   if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_COPYIN)
    1302              :     {
    1303           66 :       gfc_init_block (&cond_block);
    1304           66 :       if (GFC_DESCRIPTOR_TYPE_P (type))
    1305              :         {
    1306           48 :           tree tmp = gfc_conv_descriptor_data_get (unshare_expr (dest));
    1307           48 :           tmp = gfc_deallocate_with_status (tmp, NULL_TREE, NULL_TREE,
    1308              :                                             NULL_TREE, NULL_TREE, true, NULL,
    1309              :                                             GFC_CAF_COARRAY_NOCOARRAY);
    1310           48 :           gfc_add_expr_to_block (&cond_block, tmp);
    1311              :         }
    1312              :       else
    1313              :         {
    1314           18 :           destptr = gfc_evaluate_now (destptr, &cond_block);
    1315           18 :           gfc_add_expr_to_block (&cond_block, gfc_call_free (destptr));
    1316           18 :           gfc_add_modify (&cond_block, unshare_expr (dest),
    1317           18 :                           build_zero_cst (TREE_TYPE (dest)));
    1318              :         }
    1319           66 :       else_b = gfc_finish_block (&cond_block);
    1320              : 
    1321           66 :       cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
    1322              :                               unshare_expr (srcptr), null_pointer_node);
    1323           66 :       gfc_add_expr_to_block (&block,
    1324              :                              build3_loc (input_location, COND_EXPR,
    1325              :                                          void_type_node, cond,
    1326              :                                          then_b, else_b));
    1327              :     }
    1328              :   else
    1329          275 :     gfc_add_expr_to_block (&block, then_b);
    1330              : 
    1331          341 :   return gfc_finish_block (&block);
    1332              : }
    1333              : 
    1334              : static void
    1335           84 : gfc_omp_linear_clause_add_loop (stmtblock_t *block, tree dest, tree src,
    1336              :                                 tree add, tree nelems)
    1337              : {
    1338           84 :   stmtblock_t tmpblock;
    1339           84 :   tree desta, srca, index = gfc_create_var (gfc_array_index_type, "S");
    1340           84 :   nelems = gfc_evaluate_now (nelems, block);
    1341              : 
    1342           84 :   gfc_init_block (&tmpblock);
    1343           84 :   if (TREE_CODE (TREE_TYPE (dest)) == ARRAY_TYPE)
    1344              :     {
    1345           60 :       desta = gfc_build_array_ref (dest, index, NULL);
    1346           60 :       srca = gfc_build_array_ref (src, index, NULL);
    1347              :     }
    1348              :   else
    1349              :     {
    1350           24 :       gcc_assert (POINTER_TYPE_P (TREE_TYPE (dest)));
    1351           24 :       tree idx = fold_build2 (MULT_EXPR, sizetype,
    1352              :                               fold_convert (sizetype, index),
    1353              :                               TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (dest))));
    1354           24 :       desta = build_fold_indirect_ref (fold_build2 (POINTER_PLUS_EXPR,
    1355              :                                                     TREE_TYPE (dest), dest,
    1356              :                                                     idx));
    1357           24 :       srca = build_fold_indirect_ref (fold_build2 (POINTER_PLUS_EXPR,
    1358              :                                                    TREE_TYPE (src), src,
    1359              :                                                     idx));
    1360              :     }
    1361           84 :   gfc_add_modify (&tmpblock, desta,
    1362           84 :                   fold_build2 (PLUS_EXPR, TREE_TYPE (desta),
    1363              :                                srca, add));
    1364              : 
    1365           84 :   gfc_loopinfo loop;
    1366           84 :   gfc_init_loopinfo (&loop);
    1367           84 :   loop.dimen = 1;
    1368           84 :   loop.from[0] = gfc_index_zero_node;
    1369           84 :   loop.loopvar[0] = index;
    1370           84 :   loop.to[0] = nelems;
    1371           84 :   gfc_trans_scalarizing_loops (&loop, &tmpblock);
    1372           84 :   gfc_add_block_to_block (block, &loop.pre);
    1373           84 : }
    1374              : 
    1375              : /* Build and return code for a constructor of DEST that initializes
    1376              :    it to SRC plus ADD (ADD is scalar integer).  */
    1377              : 
    1378              : tree
    1379          108 : gfc_omp_clause_linear_ctor (tree clause, tree dest, tree src, tree add)
    1380              : {
    1381          108 :   tree type = TREE_TYPE (dest), ptr, size, nelems = NULL_TREE;
    1382          108 :   stmtblock_t block;
    1383              : 
    1384          108 :   gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR);
    1385              : 
    1386          108 :   gfc_start_block (&block);
    1387          108 :   add = gfc_evaluate_now (add, &block);
    1388              : 
    1389          108 :   if ((! GFC_DESCRIPTOR_TYPE_P (type)
    1390           24 :        || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
    1391          192 :       && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))
    1392           24 :           || !POINTER_TYPE_P (type)))
    1393              :     {
    1394           60 :       bool compute_nelts = false;
    1395           60 :       gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
    1396           60 :       if (!TYPE_DOMAIN (type)
    1397           60 :           || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE
    1398           60 :           || TYPE_MIN_VALUE (TYPE_DOMAIN (type)) == error_mark_node
    1399          120 :           || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == error_mark_node)
    1400              :         compute_nelts = true;
    1401           60 :       else if (VAR_P (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
    1402              :         {
    1403           48 :           tree a = DECL_ATTRIBUTES (TYPE_MAX_VALUE (TYPE_DOMAIN (type)));
    1404           48 :           if (lookup_attribute ("omp dummy var", a))
    1405              :             compute_nelts = true;
    1406              :         }
    1407              :       if (compute_nelts)
    1408              :         {
    1409           48 :           nelems = fold_build2 (EXACT_DIV_EXPR, sizetype,
    1410              :                                 TYPE_SIZE_UNIT (type),
    1411              :                                 TYPE_SIZE_UNIT (TREE_TYPE (type)));
    1412           48 :           nelems = size_binop (MINUS_EXPR, nelems, size_one_node);
    1413              :         }
    1414              :       else
    1415           12 :         nelems = array_type_nelts_minus_one (type);
    1416           60 :       nelems = fold_convert (gfc_array_index_type, nelems);
    1417              : 
    1418           60 :       gfc_omp_linear_clause_add_loop (&block, dest, src, add, nelems);
    1419           60 :       return gfc_finish_block (&block);
    1420              :     }
    1421              : 
    1422              :   /* Allocatable arrays in LINEAR clauses need to be allocated
    1423              :      and copied from SRC.  */
    1424           48 :   gfc_add_modify (&block, dest, src);
    1425           48 :   if (GFC_DESCRIPTOR_TYPE_P (type))
    1426              :     {
    1427           24 :       tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
    1428           24 :       size = gfc_conv_descriptor_ubound_get (dest, rank);
    1429           24 :       size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
    1430              :                               size,
    1431              :                               gfc_conv_descriptor_lbound_get (dest, rank));
    1432           24 :       size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
    1433              :                               size, gfc_index_one_node);
    1434           24 :       if (GFC_TYPE_ARRAY_RANK (type) > 1)
    1435            0 :         size = fold_build2_loc (input_location, MULT_EXPR,
    1436              :                                 gfc_array_index_type, size,
    1437              :                                 gfc_conv_descriptor_stride_get (dest, rank));
    1438           24 :       tree esize = fold_convert (gfc_array_index_type,
    1439              :                                  TYPE_SIZE_UNIT (gfc_get_element_type (type)));
    1440           24 :       nelems = gfc_evaluate_now (unshare_expr (size), &block);
    1441           24 :       size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
    1442              :                               nelems, unshare_expr (esize));
    1443           24 :       size = gfc_evaluate_now (fold_convert (size_type_node, size),
    1444              :                                &block);
    1445           24 :       nelems = fold_build2_loc (input_location, MINUS_EXPR,
    1446              :                                 gfc_array_index_type, nelems,
    1447              :                                 gfc_index_one_node);
    1448              :     }
    1449              :   else
    1450           24 :     size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
    1451           48 :   ptr = gfc_create_var (pvoid_type_node, NULL);
    1452           48 :   gfc_allocate_using_malloc (&block, ptr, size, NULL_TREE);
    1453           48 :   if (GFC_DESCRIPTOR_TYPE_P (type))
    1454              :     {
    1455           24 :       gfc_conv_descriptor_data_set (&block, unshare_expr (dest), ptr);
    1456           24 :       tree etype = gfc_get_element_type (type);
    1457           24 :       ptr = fold_convert (build_pointer_type (etype), ptr);
    1458           24 :       tree srcptr = gfc_conv_descriptor_data_get (unshare_expr (src));
    1459           24 :       srcptr = fold_convert (build_pointer_type (etype), srcptr);
    1460           24 :       gfc_omp_linear_clause_add_loop (&block, ptr, srcptr, add, nelems);
    1461              :     }
    1462              :   else
    1463              :     {
    1464           24 :       gfc_add_modify (&block, unshare_expr (dest),
    1465           24 :                       fold_convert (TREE_TYPE (dest), ptr));
    1466           24 :       ptr = fold_convert (TREE_TYPE (dest), ptr);
    1467           24 :       tree dstm = build_fold_indirect_ref (ptr);
    1468           24 :       tree srcm = build_fold_indirect_ref (unshare_expr (src));
    1469           24 :       gfc_add_modify (&block, dstm,
    1470           24 :                       fold_build2 (PLUS_EXPR, TREE_TYPE (add), srcm, add));
    1471              :     }
    1472           48 :   return gfc_finish_block (&block);
    1473              : }
    1474              : 
    1475              : /* Build and return code destructing DECL.  Return NULL if nothing
    1476              :    to be done.  */
    1477              : 
    1478              : tree
    1479        32202 : gfc_omp_clause_dtor (tree clause, tree decl)
    1480              : {
    1481        32202 :   tree type = TREE_TYPE (decl), tem;
    1482        32202 :   tree decl_type = TREE_TYPE (OMP_CLAUSE_DECL (clause));
    1483        32202 :   tree orig_decl = OMP_CLAUSE_DECL (clause);
    1484              : 
    1485        32202 :   if (DECL_ARTIFICIAL (orig_decl)
    1486        11947 :       && DECL_LANG_SPECIFIC (orig_decl)
    1487        32564 :       && GFC_DECL_SAVED_DESCRIPTOR (orig_decl))
    1488              :     {
    1489          346 :       orig_decl = GFC_DECL_SAVED_DESCRIPTOR (orig_decl);
    1490          346 :       decl_type = TREE_TYPE (orig_decl);
    1491              :     }
    1492              : 
    1493              :   /* Only pointer association was privatized; cf. gfc_omp_clause_copy_ctor.
    1494              :      Scalar class pointers must not finalize or free their targets here.  */
    1495        32202 :   if (DECL_P (orig_decl)
    1496        32202 :       && (GFC_DECL_ASSOCIATE_VAR_P (orig_decl)
    1497        32175 :           || GFC_DECL_GET_SCALAR_POINTER (orig_decl)
    1498        32130 :           || gfc_is_class_pointer_type (decl_type)))
    1499              :     return NULL_TREE;
    1500        32118 :   if (gfc_is_polymorphic_nonptr (decl_type))
    1501              :     {
    1502           37 :       if (POINTER_TYPE_P (decl_type))
    1503           24 :         decl_type = TREE_TYPE (decl_type);
    1504           37 :       decl_type = TREE_TYPE (TYPE_FIELDS (decl_type));
    1505           37 :       if (GFC_DESCRIPTOR_TYPE_P (decl_type) || GFC_ARRAY_TYPE_P (decl_type))
    1506            0 :         fatal_error (input_location,
    1507              :                      "Sorry, polymorphic arrays not yet supported for "
    1508              :                      "firstprivate");
    1509           37 :       stmtblock_t block, cond_block;
    1510           37 :       gfc_start_block (&block);
    1511           37 :       gfc_init_block (&cond_block);
    1512           37 :       tree final = gfc_class_vtab_final_get (decl);
    1513           37 :       tree size = fold_convert (size_type_node, gfc_class_vtab_size_get (decl));
    1514           37 :       gfc_se se;
    1515           37 :       gfc_init_se (&se, NULL);
    1516           37 :       symbol_attribute attr = {};
    1517           37 :       tree data = gfc_class_data_get (decl);
    1518           37 :       tree desc = gfc_conv_scalar_to_descriptor (&se, data, attr);
    1519              : 
    1520              :       /* Call class->_vpt->_finalize + free.  */
    1521           37 :       tree call = build_fold_indirect_ref (final);
    1522           37 :       call = build_call_expr_loc (input_location, call, 3,
    1523              :                                   gfc_build_addr_expr (NULL, desc),
    1524              :                                   size, boolean_false_node);
    1525           37 :       gfc_add_block_to_block (&cond_block, &se.pre);
    1526           37 :       gfc_add_expr_to_block (&cond_block, fold_convert (void_type_node, call));
    1527           37 :       gfc_add_block_to_block (&cond_block, &se.post);
    1528              :       /* Create: if (_vtab && _final) <cond_block>  */
    1529           37 :       tree cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
    1530              :                                    gfc_class_vptr_get (decl),
    1531              :                                    null_pointer_node);
    1532           37 :       tree cond2 = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
    1533              :                                    final, null_pointer_node);
    1534           37 :       cond = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
    1535              :                               boolean_type_node, cond, cond2);
    1536           37 :       gfc_add_expr_to_block (&block, build3_loc (input_location, COND_EXPR,
    1537              :                                  void_type_node, cond,
    1538              :                                  gfc_finish_block (&cond_block), NULL_TREE));
    1539           37 :       call = builtin_decl_explicit (BUILT_IN_FREE);
    1540           37 :       call = build_call_expr_loc (input_location, call, 1, data);
    1541           37 :       gfc_add_expr_to_block (&block, fold_convert (void_type_node, call));
    1542           37 :       return gfc_finish_block (&block);
    1543              :     }
    1544              : 
    1545        32081 :   if ((! GFC_DESCRIPTOR_TYPE_P (type)
    1546          447 :        || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
    1547        32138 :       && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))
    1548          187 :           || !POINTER_TYPE_P (type)))
    1549              :     {
    1550        31506 :       if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause), false))
    1551          142 :         return gfc_walk_alloc_comps (decl, NULL_TREE,
    1552           71 :                                      OMP_CLAUSE_DECL (clause),
    1553           71 :                                      WALK_ALLOC_COMPS_DTOR);
    1554              :       return NULL_TREE;
    1555              :     }
    1556              : 
    1557          575 :   if (GFC_DESCRIPTOR_TYPE_P (type))
    1558              :     {
    1559              :       /* Allocatable arrays in FIRSTPRIVATE/LASTPRIVATE etc. clauses need
    1560              :          to be deallocated if they were allocated.  */
    1561          390 :       tem = gfc_conv_descriptor_data_get (decl);
    1562          390 :       tem = gfc_deallocate_with_status (tem, NULL_TREE, NULL_TREE, NULL_TREE,
    1563              :                                         NULL_TREE, true, NULL,
    1564              :                                         GFC_CAF_COARRAY_NOCOARRAY);
    1565              :     }
    1566              :   else
    1567          185 :     tem = gfc_call_free (decl);
    1568          575 :   tem = gfc_omp_unshare_expr (tem);
    1569              : 
    1570          575 :   if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause), false))
    1571              :     {
    1572           86 :       stmtblock_t block;
    1573           86 :       tree then_b;
    1574              : 
    1575           86 :       gfc_init_block (&block);
    1576          172 :       gfc_add_expr_to_block (&block,
    1577              :                              gfc_walk_alloc_comps (decl, NULL_TREE,
    1578           86 :                                                    OMP_CLAUSE_DECL (clause),
    1579              :                                                    WALK_ALLOC_COMPS_DTOR));
    1580           86 :       gfc_add_expr_to_block (&block, tem);
    1581           86 :       then_b = gfc_finish_block (&block);
    1582              : 
    1583           86 :       tem = fold_convert (pvoid_type_node,
    1584              :                           GFC_DESCRIPTOR_TYPE_P (type)
    1585              :                           ? gfc_conv_descriptor_data_get (decl) : decl);
    1586           86 :       tem = unshare_expr (tem);
    1587           86 :       tree cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
    1588              :                                    tem, null_pointer_node);
    1589           86 :       tem = build3_loc (input_location, COND_EXPR, void_type_node, cond,
    1590              :                         then_b, build_empty_stmt (input_location));
    1591              :     }
    1592              :   return tem;
    1593              : }
    1594              : 
    1595              : /* Build a conditional expression in BLOCK.  If COND_VAL is not
    1596              :    null, then the block THEN_B is executed, otherwise ELSE_VAL
    1597              :    is assigned to VAL.  */
    1598              : 
    1599              : static void
    1600         1026 : gfc_build_cond_assign (stmtblock_t *block, tree val, tree cond_val,
    1601              :                        tree then_b, tree else_val)
    1602              : {
    1603         1026 :   stmtblock_t cond_block;
    1604         1026 :   tree else_b = NULL_TREE;
    1605         1026 :   tree val_ty = TREE_TYPE (val);
    1606              : 
    1607         1026 :   if (else_val)
    1608              :     {
    1609         1026 :       gfc_init_block (&cond_block);
    1610         1026 :       gfc_add_modify (&cond_block, val, fold_convert (val_ty, else_val));
    1611         1026 :       else_b = gfc_finish_block (&cond_block);
    1612              :     }
    1613         1026 :   gfc_add_expr_to_block (block,
    1614              :                          build3_loc (input_location, COND_EXPR, void_type_node,
    1615              :                                      cond_val, then_b, else_b));
    1616         1026 : }
    1617              : 
    1618              : /* Build a conditional expression in BLOCK, returning a temporary
    1619              :    variable containing the result.  If COND_VAL is not null, then
    1620              :    THEN_VAL will be assigned to the variable, otherwise ELSE_VAL
    1621              :    is assigned.
    1622              :  */
    1623              : 
    1624              : static tree
    1625         1025 : gfc_build_cond_assign_expr (stmtblock_t *block, tree cond_val,
    1626              :                             tree then_val, tree else_val)
    1627              : {
    1628         1025 :   tree val;
    1629         1025 :   tree val_ty = TREE_TYPE (then_val);
    1630         1025 :   stmtblock_t cond_block;
    1631              : 
    1632         1025 :   val = create_tmp_var (val_ty);
    1633              : 
    1634         1025 :   gfc_init_block (&cond_block);
    1635         1025 :   gfc_add_modify (&cond_block, val, then_val);
    1636         1025 :   tree then_b = gfc_finish_block (&cond_block);
    1637              : 
    1638         1025 :   gfc_build_cond_assign (block, val, cond_val, then_b, else_val);
    1639              : 
    1640         1025 :   return val;
    1641              : }
    1642              : 
    1643              : void
    1644        29305 : gfc_omp_finish_clause (tree c, gimple_seq *pre_p, bool openacc)
    1645              : {
    1646        29305 :   if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
    1647              :     return;
    1648              : 
    1649         7159 :   tree decl = OMP_CLAUSE_DECL (c);
    1650         7159 :   location_t loc = OMP_CLAUSE_LOCATION (c);
    1651              : 
    1652              :   /* Assumed-size arrays can't be mapped implicitly, they have to be
    1653              :      mapped explicitly using array sections.  */
    1654         7159 :   if (TREE_CODE (decl) == PARM_DECL
    1655         1047 :       && GFC_ARRAY_TYPE_P (TREE_TYPE (decl))
    1656          371 :       && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (decl)) == GFC_ARRAY_UNKNOWN
    1657         7530 :       && GFC_TYPE_ARRAY_UBOUND (TREE_TYPE (decl),
    1658              :                                 GFC_TYPE_ARRAY_RANK (TREE_TYPE (decl)) - 1)
    1659              :          == NULL)
    1660              :     {
    1661            1 :       error_at (OMP_CLAUSE_LOCATION (c),
    1662              :                 "implicit mapping of assumed size array %qD", decl);
    1663            1 :       return;
    1664              :     }
    1665              : 
    1666         7158 :   tree c2 = NULL_TREE, c3 = NULL_TREE, c4 = NULL_TREE;
    1667         7158 :   tree present = gfc_omp_check_optional_argument (decl, true);
    1668         7158 :   tree orig_decl = NULL_TREE;
    1669         7158 :   if (POINTER_TYPE_P (TREE_TYPE (decl)))
    1670              :     {
    1671         1294 :       if (!gfc_omp_privatize_by_reference (decl)
    1672          156 :           && !GFC_DECL_GET_SCALAR_POINTER (decl)
    1673           93 :           && !GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
    1674            3 :           && !GFC_DECL_CRAY_POINTEE (decl)
    1675         1297 :           && !GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
    1676              :         return;
    1677         1291 :       orig_decl = decl;
    1678              : 
    1679         1291 :       c4 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
    1680         1291 :       OMP_CLAUSE_SET_MAP_KIND (c4, GOMP_MAP_POINTER);
    1681         1291 :       OMP_CLAUSE_DECL (c4) = decl;
    1682         1291 :       OMP_CLAUSE_SIZE (c4) = size_int (0);
    1683         1291 :       decl = build_fold_indirect_ref (decl);
    1684         1291 :       if (present
    1685         1291 :           && (GFC_DECL_GET_SCALAR_POINTER (orig_decl)
    1686          269 :               || GFC_DECL_GET_SCALAR_ALLOCATABLE (orig_decl)))
    1687              :         {
    1688           67 :           c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
    1689           67 :           OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_POINTER);
    1690           67 :           OMP_CLAUSE_DECL (c2) = unshare_expr (decl);
    1691           67 :           OMP_CLAUSE_SIZE (c2) = size_int (0);
    1692              : 
    1693           67 :           stmtblock_t block;
    1694           67 :           gfc_start_block (&block);
    1695           67 :           tree ptr = gfc_build_cond_assign_expr (&block, present,
    1696              :                                                  unshare_expr (decl),
    1697              :                                                  null_pointer_node);
    1698           67 :           gimplify_and_add (gfc_finish_block (&block), pre_p);
    1699           67 :           ptr = build_fold_indirect_ref (ptr);
    1700           67 :           OMP_CLAUSE_DECL (c) = ptr;
    1701           67 :           OMP_CLAUSE_SIZE (c) = TYPE_SIZE_UNIT (TREE_TYPE (ptr));
    1702              :         }
    1703              :       else
    1704              :         {
    1705         1224 :           OMP_CLAUSE_DECL (c) = decl;
    1706         1224 :           OMP_CLAUSE_SIZE (c) = NULL_TREE;
    1707              :         }
    1708         1291 :       if (TREE_CODE (TREE_TYPE (orig_decl)) == REFERENCE_TYPE
    1709         1291 :           && (GFC_DECL_GET_SCALAR_POINTER (orig_decl)
    1710          391 :               || GFC_DECL_GET_SCALAR_ALLOCATABLE (orig_decl)))
    1711              :         {
    1712           67 :           c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
    1713           67 :           OMP_CLAUSE_SET_MAP_KIND (c3, GOMP_MAP_POINTER);
    1714           67 :           OMP_CLAUSE_DECL (c3) = decl;
    1715           67 :           OMP_CLAUSE_SIZE (c3) = size_int (0);
    1716           67 :           decl = build_fold_indirect_ref (decl);
    1717           67 :           OMP_CLAUSE_DECL (c) = unshare_expr (decl);
    1718              :         }
    1719              :     }
    1720         7155 :   if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
    1721              :     {
    1722         1731 :       stmtblock_t block;
    1723         1731 :       gfc_start_block (&block);
    1724         1731 :       tree type = TREE_TYPE (decl);
    1725         1731 :       tree ptr = gfc_conv_descriptor_data_get (decl);
    1726              : 
    1727              :       /* OpenMP: automatically map pointer targets with the pointer;
    1728              :          hence, always update the descriptor/pointer itself.
    1729              :          NOTE: This also remaps the pointer for allocatable arrays with
    1730              :          'target' attribute which also don't have the 'restrict' qualifier.  */
    1731         1731 :       bool always_modifier = false;
    1732              : 
    1733         1731 :       if (!openacc
    1734         1731 :           && !(TYPE_QUALS (TREE_TYPE (ptr)) & TYPE_QUAL_RESTRICT))
    1735              :         always_modifier = true;
    1736              : 
    1737         1731 :       if (present)
    1738           56 :         ptr = gfc_build_cond_assign_expr (&block, present, ptr,
    1739              :                                           null_pointer_node);
    1740         1731 :       gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
    1741         1731 :       ptr = build_fold_indirect_ref (ptr);
    1742         1731 :       OMP_CLAUSE_DECL (c) = ptr;
    1743         1731 :       c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
    1744         1731 :       OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_TO_PSET);
    1745         1731 :       if (present)
    1746              :         {
    1747           56 :           ptr = create_tmp_var (TREE_TYPE (TREE_OPERAND (decl, 0)));
    1748           56 :           gfc_add_modify (&block, ptr, TREE_OPERAND (decl, 0));
    1749              : 
    1750           56 :           OMP_CLAUSE_DECL (c2) = build_fold_indirect_ref (ptr);
    1751              :         }
    1752              :       else
    1753         1675 :         OMP_CLAUSE_DECL (c2) = decl;
    1754         1731 :       OMP_CLAUSE_SIZE (c2) = TYPE_SIZE_UNIT (type);
    1755         1731 :       c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
    1756         3251 :       OMP_CLAUSE_SET_MAP_KIND (c3, always_modifier ? GOMP_MAP_ALWAYS_POINTER
    1757              :                                                    : GOMP_MAP_POINTER);
    1758         1731 :       if (present)
    1759              :         {
    1760           56 :           ptr = gfc_conv_descriptor_data_get (unshare_expr (decl));
    1761           56 :           ptr = gfc_build_addr_expr (NULL, ptr);
    1762           56 :           ptr = gfc_build_cond_assign_expr (&block, present,
    1763              :                                             ptr, null_pointer_node);
    1764           56 :           ptr = build_fold_indirect_ref (ptr);
    1765           56 :           OMP_CLAUSE_DECL (c3) = ptr;
    1766              :         }
    1767              :       else
    1768         1675 :         OMP_CLAUSE_DECL (c3) = gfc_conv_descriptor_data_get (decl);
    1769         1731 :       OMP_CLAUSE_SIZE (c3) = size_int (0);
    1770         1731 :       tree size = create_tmp_var (gfc_array_index_type);
    1771         1731 :       tree elemsz = TYPE_SIZE_UNIT (gfc_get_element_type (type));
    1772         1731 :       elemsz = fold_convert (gfc_array_index_type, elemsz);
    1773              : 
    1774         1731 :       if (orig_decl == NULL_TREE)
    1775         1497 :         orig_decl = decl;
    1776         1731 :       if (!openacc
    1777         1731 :           && gfc_has_alloc_comps (type, orig_decl, true))
    1778              :         {
    1779              :           /* Save array descriptor for use in gfc_omp_deep_mapping{,_p,_cnt};
    1780              :              force evaluate to ensure that it is not gimplified + is a decl.  */
    1781            3 :           gfc_allocate_lang_decl (size);
    1782            3 :           GFC_DECL_SAVED_DESCRIPTOR (size) = orig_decl;
    1783              :         }
    1784         1731 :       enum gfc_array_kind akind = GFC_TYPE_ARRAY_AKIND (type);
    1785         1731 :       if (akind == GFC_ARRAY_ALLOCATABLE
    1786              :           || akind == GFC_ARRAY_POINTER
    1787         1731 :           || akind == GFC_ARRAY_POINTER_CONT
    1788         1731 :           || akind == GFC_ARRAY_ASSUMED_RANK_ALLOCATABLE
    1789              :           || akind == GFC_ARRAY_ASSUMED_RANK_POINTER
    1790            1 :           || akind == GFC_ARRAY_ASSUMED_RANK_POINTER_CONT)
    1791              :         {
    1792         1730 :           stmtblock_t cond_block;
    1793         1730 :           tree tem, then_b, else_b, zero, cond;
    1794              : 
    1795         1730 :           int rank = ((akind == GFC_ARRAY_ASSUMED_RANK_ALLOCATABLE
    1796              :                        || akind == GFC_ARRAY_ASSUMED_RANK_POINTER
    1797         1730 :                        || akind == GFC_ARRAY_ASSUMED_RANK_POINTER_CONT)
    1798         1730 :                       ? -1 : GFC_TYPE_ARRAY_RANK (type));
    1799         1730 :           gfc_init_block (&cond_block);
    1800         1730 :           tem = gfc_full_array_size (&cond_block, unshare_expr (decl), rank);
    1801         1730 :           gfc_add_modify (&cond_block, size, tem);
    1802         1730 :           gfc_add_modify (&cond_block, size,
    1803              :                           fold_build2 (MULT_EXPR, gfc_array_index_type,
    1804              :                                        size, elemsz));
    1805         1730 :           then_b = gfc_finish_block (&cond_block);
    1806         1730 :           gfc_init_block (&cond_block);
    1807         1730 :           zero = build_int_cst (gfc_array_index_type, 0);
    1808         1730 :           gfc_add_modify (&cond_block, size, zero);
    1809         1730 :           else_b = gfc_finish_block (&cond_block);
    1810         1730 :           tem = gfc_conv_descriptor_data_get (unshare_expr (decl));
    1811         1730 :           tem = fold_convert (pvoid_type_node, tem);
    1812         1730 :           cond = fold_build2_loc (loc, NE_EXPR,
    1813              :                                   boolean_type_node, tem, null_pointer_node);
    1814         1730 :           if (present)
    1815              :             {
    1816           55 :               cond = fold_build2_loc (loc, TRUTH_ANDIF_EXPR,
    1817              :                                       boolean_type_node, present, cond);
    1818              :             }
    1819         1730 :           gfc_add_expr_to_block (&block, build3_loc (loc, COND_EXPR,
    1820              :                                                      void_type_node, cond,
    1821              :                                                      then_b, else_b));
    1822         1730 :         }
    1823            1 :       else if (present)
    1824              :         {
    1825            1 :           stmtblock_t cond_block;
    1826            1 :           tree then_b;
    1827              : 
    1828            1 :           int rank = ((akind == GFC_ARRAY_ASSUMED_RANK
    1829            1 :                        || akind == GFC_ARRAY_ASSUMED_RANK_CONT)
    1830            1 :                       ? -1 : GFC_TYPE_ARRAY_RANK (type));
    1831            1 :           gfc_init_block (&cond_block);
    1832            1 :           gfc_add_modify (&cond_block, size,
    1833              :                           gfc_full_array_size (&cond_block, unshare_expr (decl),
    1834              :                                                rank));
    1835            1 :           gfc_add_modify (&cond_block, size,
    1836              :                           fold_build2 (MULT_EXPR, gfc_array_index_type,
    1837              :                                        size, elemsz));
    1838            1 :           then_b = gfc_finish_block (&cond_block);
    1839              : 
    1840            1 :           gfc_build_cond_assign (&block, size, present, then_b,
    1841              :                                  build_int_cst (gfc_array_index_type, 0));
    1842              :         }
    1843              :       else
    1844              :         {
    1845            0 :           int rank = ((akind == GFC_ARRAY_ASSUMED_RANK
    1846            0 :                        || akind == GFC_ARRAY_ASSUMED_RANK_CONT)
    1847            0 :                       ? -1 : GFC_TYPE_ARRAY_RANK (type));
    1848            0 :           gfc_add_modify (&block, size,
    1849              :                           gfc_full_array_size (&block, unshare_expr (decl),
    1850              :                                                rank));
    1851            0 :           gfc_add_modify (&block, size,
    1852              :                           fold_build2 (MULT_EXPR, gfc_array_index_type,
    1853              :                                        size, elemsz));
    1854              :         }
    1855         1731 :       OMP_CLAUSE_SIZE (c) = size;
    1856         1731 :       tree stmt = gfc_finish_block (&block);
    1857         1731 :       gimplify_and_add (stmt, pre_p);
    1858              :     }
    1859              :   else
    1860              :     {
    1861         5424 :       if (OMP_CLAUSE_SIZE (c) == NULL_TREE)
    1862              :         {
    1863         1202 :           if (DECL_P (decl))
    1864          212 :             OMP_CLAUSE_SIZE (c) = DECL_SIZE_UNIT (decl);
    1865              :           else
    1866              :             {
    1867          990 :               tree type = TREE_TYPE (decl);
    1868          990 :               tree size = TYPE_SIZE_UNIT (type);
    1869              :               /* For variable-length character types, TYPE_SIZE_UNIT is a
    1870              :                  SAVE_EXPR.  Gimplifying the SAVE_EXPR (here or elsewhere)
    1871              :                  resolves it in place, embedding a gimple temporary that
    1872              :                  later causes an ICE in remap_type during inlining because
    1873              :                  the temporary is not in scope (PR101760, PR102314).
    1874              :                  Compute the size from the array domain and element size
    1875              :                  to decouple completely from the type's SAVE_EXPRs.  */
    1876          990 :               if (size
    1877          990 :                   && TREE_CODE (type) == ARRAY_TYPE
    1878          536 :                   && TYPE_DOMAIN (type)
    1879          536 :                   && TYPE_MAX_VALUE (TYPE_DOMAIN (type))
    1880         1526 :                   && !TREE_CONSTANT (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
    1881              :                 {
    1882          316 :                   tree len = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
    1883          316 :                   tree lb = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
    1884          316 :                   tree eltsz = TYPE_SIZE_UNIT (TREE_TYPE (type));
    1885          316 :                   len = fold_build2 (MINUS_EXPR, TREE_TYPE (len), len, lb);
    1886          316 :                   len = fold_build2 (PLUS_EXPR, TREE_TYPE (len), len,
    1887              :                                      build_one_cst (TREE_TYPE (len)));
    1888          316 :                   size = fold_build2 (MULT_EXPR, sizetype,
    1889              :                                       fold_convert (sizetype, len),
    1890              :                                       fold_convert (sizetype, eltsz));
    1891              :                 }
    1892          990 :               OMP_CLAUSE_SIZE (c) = size;
    1893              :             }
    1894              :         }
    1895              : 
    1896         5424 :       tree type = TREE_TYPE (decl);
    1897         5424 :       if (POINTER_TYPE_P (type) && POINTER_TYPE_P (TREE_TYPE (type)))
    1898            0 :         type = TREE_TYPE (type);
    1899         5424 :       if (!openacc
    1900         5424 :           && orig_decl != NULL_TREE
    1901         5424 :           && gfc_has_alloc_comps (type, orig_decl, true))
    1902              :         {
    1903              :           /* Save array descriptor for use in gfc_omp_deep_mapping{,_p,_cnt};
    1904              :              force evaluate to ensure that it is not gimplified + is a decl.  */
    1905           19 :           tree size = create_tmp_var (TREE_TYPE (OMP_CLAUSE_SIZE (c)));
    1906           19 :           gfc_allocate_lang_decl (size);
    1907           19 :           GFC_DECL_SAVED_DESCRIPTOR (size) = orig_decl;
    1908           19 :           gimplify_assign (size, OMP_CLAUSE_SIZE (c), pre_p);
    1909           19 :           OMP_CLAUSE_SIZE (c) = size;
    1910              :         }
    1911              :     }
    1912         7155 :   tree last = c;
    1913         7155 :   if (gimplify_expr (&OMP_CLAUSE_SIZE (c), pre_p,
    1914              :                      NULL, is_gimple_val, fb_rvalue) == GS_ERROR)
    1915            0 :     OMP_CLAUSE_SIZE (c) = size_int (0);
    1916         7155 :   if (c2)
    1917              :     {
    1918         1798 :       OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (last);
    1919         1798 :       OMP_CLAUSE_CHAIN (last) = c2;
    1920         1798 :       last = c2;
    1921              :     }
    1922         7155 :   if (c3)
    1923              :     {
    1924         1798 :       OMP_CLAUSE_CHAIN (c3) = OMP_CLAUSE_CHAIN (last);
    1925         1798 :       OMP_CLAUSE_CHAIN (last) = c3;
    1926         1798 :       last = c3;
    1927              :     }
    1928         7155 :   if (c4)
    1929              :     {
    1930         1291 :       OMP_CLAUSE_CHAIN (c4) = OMP_CLAUSE_CHAIN (last);
    1931         1291 :       OMP_CLAUSE_CHAIN (last) = c4;
    1932              :     }
    1933              : }
    1934              : 
    1935              : 
    1936              : /* map(<flag>: data [len: <size>])
    1937              :    map(attach: &data [bias: <bias>])
    1938              :    offset += 2; offset_data += 2 */
    1939              : static void
    1940          645 : gfc_omp_deep_mapping_map (tree data, tree size, unsigned HOST_WIDE_INT tkind,
    1941              :                           location_t loc, tree data_array, tree sizes_array,
    1942              :                           tree kinds_array, tree offset_data, tree offset,
    1943              :                           gimple_seq *seq, const gimple *ctx)
    1944              : {
    1945          645 :   tree one = build_int_cst (size_type_node, 1);
    1946              : 
    1947          645 :   STRIP_NOPS (data);
    1948          645 :   if (!POINTER_TYPE_P (TREE_TYPE (data)))
    1949              :     {
    1950          205 :       gcc_assert (TREE_CODE (data) == INDIRECT_REF);
    1951          205 :       data = TREE_OPERAND (data, 0);
    1952              :     }
    1953              : 
    1954              :   /* data_array[offset_data] = data; */
    1955          645 :   tree tmp = build4 (ARRAY_REF, TREE_TYPE (TREE_TYPE (data_array)),
    1956              :                      unshare_expr (data_array), offset_data,
    1957              :                      NULL_TREE, NULL_TREE);
    1958          645 :   gimplify_assign (tmp, data, seq);
    1959              : 
    1960              :   /* offset_data++ */
    1961          645 :   tmp = build2_loc (loc, PLUS_EXPR, size_type_node, offset_data, one);
    1962          645 :   gimplify_assign (offset_data, tmp, seq);
    1963              : 
    1964              :   /* data_array[offset_data] = &data; */
    1965          645 :   tmp = build4 (ARRAY_REF, TREE_TYPE (TREE_TYPE (data_array)),
    1966              :                 unshare_expr (data_array),
    1967              :                 offset_data, NULL_TREE, NULL_TREE);
    1968          645 :   gimplify_assign (tmp, build_fold_addr_expr (data), seq);
    1969              : 
    1970              :   /* offset_data++ */
    1971          645 :   tmp = build2_loc (loc, PLUS_EXPR, size_type_node, offset_data, one);
    1972          645 :   gimplify_assign (offset_data, tmp, seq);
    1973              : 
    1974              :   /* sizes_array[offset] = size */
    1975          645 :   tmp = build2_loc (loc, MULT_EXPR, size_type_node,
    1976          645 :                     TYPE_SIZE_UNIT (size_type_node), offset);
    1977          645 :   tmp = build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (sizes_array),
    1978              :                     sizes_array, tmp);
    1979          645 :   gimple_seq seq2 = NULL;
    1980          645 :   tmp = force_gimple_operand (tmp, &seq2, true, NULL_TREE);
    1981          645 :   gimple_seq_add_seq (seq, seq2);
    1982          645 :   tmp = build_fold_indirect_ref_loc (loc, tmp);
    1983          645 :   gimplify_assign (tmp, size, seq);
    1984              : 
    1985              :   /* FIXME: tkind |= talign << talign_shift; */
    1986              :   /* kinds_array[offset] = tkind. */
    1987          645 :   tmp = build2_loc (loc, MULT_EXPR, size_type_node,
    1988          645 :                     TYPE_SIZE_UNIT (short_unsigned_type_node), offset);
    1989          645 :   tmp = build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (kinds_array),
    1990              :                     kinds_array, tmp);
    1991          645 :   seq2 = NULL;
    1992          645 :   tmp = force_gimple_operand (tmp, &seq2, true, NULL_TREE);
    1993          645 :   gimple_seq_add_seq (seq, seq2);
    1994          645 :   tmp = build_fold_indirect_ref_loc (loc, tmp);
    1995          645 :   gimplify_assign (tmp, build_int_cst (short_unsigned_type_node, tkind), seq);
    1996              : 
    1997              :   /* offset++ */
    1998          645 :   tmp = build2_loc (loc, PLUS_EXPR, size_type_node, offset, one);
    1999          645 :   gimplify_assign (offset, tmp, seq);
    2000              : 
    2001              :   /* sizes_array[offset] = bias (= 0).  */
    2002          645 :   tmp = build2_loc (loc, MULT_EXPR, size_type_node,
    2003          645 :                     TYPE_SIZE_UNIT (size_type_node), offset);
    2004          645 :   tmp = build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (sizes_array),
    2005              :                     sizes_array, tmp);
    2006          645 :   seq2 = NULL;
    2007          645 :   tmp = force_gimple_operand (tmp, &seq2, true, NULL_TREE);
    2008          645 :   gimple_seq_add_seq (seq, seq2);
    2009          645 :   tmp = build_fold_indirect_ref_loc (loc, tmp);
    2010          645 :   gimplify_assign (tmp, build_zero_cst (size_type_node), seq);
    2011              : 
    2012          645 :   gcc_assert (gimple_code (ctx) == GIMPLE_OMP_TARGET);
    2013          645 :   tkind = (gimple_omp_target_kind (ctx) == GF_OMP_TARGET_KIND_EXIT_DATA
    2014          645 :            ? GOMP_MAP_DETACH : GOMP_MAP_ATTACH);
    2015              : 
    2016              :   /* kinds_array[offset] = tkind. */
    2017          645 :   tmp = build2_loc (loc, MULT_EXPR, size_type_node,
    2018          645 :                     TYPE_SIZE_UNIT (short_unsigned_type_node), offset);
    2019          645 :   tmp = build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (kinds_array),
    2020              :                     kinds_array, tmp);
    2021          645 :   seq2 = NULL;
    2022          645 :   tmp = force_gimple_operand (tmp, &seq2, true, NULL_TREE);
    2023          645 :   gimple_seq_add_seq (seq, seq2);
    2024          645 :   tmp = build_fold_indirect_ref_loc (loc, tmp);
    2025          645 :   gimplify_assign (tmp, build_int_cst (short_unsigned_type_node, tkind), seq);
    2026              : 
    2027              :   /* offset++ */
    2028          645 :   tmp = build2_loc (loc, PLUS_EXPR, size_type_node, offset, one);
    2029          645 :   gimplify_assign (offset, tmp, seq);
    2030          645 : }
    2031              : 
    2032              : static void gfc_omp_deep_mapping_item (bool, bool, bool, location_t, tree,
    2033              :                                        tree *, unsigned HOST_WIDE_INT, tree,
    2034              :                                        tree, tree, tree, tree, tree,
    2035              :                                        gimple_seq *, const gimple *, bool *);
    2036              : 
    2037              : /* Map allocatable components.  */
    2038              : static void
    2039          926 : gfc_omp_deep_mapping_comps (bool is_cnt, location_t loc, tree decl,
    2040              :                             tree *token, unsigned HOST_WIDE_INT tkind,
    2041              :                             tree data_array, tree sizes_array, tree kinds_array,
    2042              :                             tree offset_data, tree offset, tree num,
    2043              :                             gimple_seq *seq, const gimple *ctx,
    2044              :                             bool *poly_warned)
    2045              : {
    2046          926 :   tree type = TREE_TYPE (decl);
    2047          926 :   if (TREE_CODE (type) != RECORD_TYPE)
    2048              :     return;
    2049         2562 :   for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
    2050              :     {
    2051         1640 :       type = TREE_TYPE (field);
    2052         1640 :       if (gfc_is_polymorphic_nonptr (type)
    2053         1438 :           || GFC_DECL_GET_SCALAR_ALLOCATABLE (field)
    2054         2800 :           || (GFC_DESCRIPTOR_TYPE_P (type)
    2055          770 :               && GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE))
    2056              :         {
    2057         1250 :           tree tmp = fold_build3_loc (loc, COMPONENT_REF, TREE_TYPE (field),
    2058              :                                       decl, field, NULL_TREE);
    2059         1250 :           gfc_omp_deep_mapping_item (is_cnt, true, true, loc, tmp, token,
    2060              :                                      tkind, data_array, sizes_array,
    2061              :                                      kinds_array, offset_data, offset, num,
    2062              :                                      seq, ctx, poly_warned);
    2063              :         }
    2064          390 :       else if (GFC_DECL_GET_SCALAR_POINTER (field)
    2065          390 :                || GFC_DESCRIPTOR_TYPE_P (type))
    2066            0 :         continue;
    2067          390 :       else if (gfc_has_alloc_comps (TREE_TYPE (field), field, false))
    2068              :         {
    2069          104 :           tree tmp = fold_build3_loc (loc, COMPONENT_REF, TREE_TYPE (field),
    2070              :                                       decl, field, NULL_TREE);
    2071          104 :           if (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE)
    2072           40 :             gfc_omp_deep_mapping_item (is_cnt, false, false, loc, tmp,
    2073              :                                        token, tkind, data_array, sizes_array,
    2074              :                                        kinds_array, offset_data, offset, num,
    2075              :                                        seq, ctx, poly_warned);
    2076              :           else
    2077           64 :             gfc_omp_deep_mapping_comps (is_cnt, loc, tmp, token, tkind,
    2078              :                                         data_array, sizes_array, kinds_array,
    2079              :                                         offset_data, offset, num, seq, ctx,
    2080              :                                         poly_warned);
    2081              :         }
    2082              :     }
    2083              : }
    2084              : 
    2085              : static void
    2086          944 : gfc_omp_gen_simple_loop (tree var, tree begin, tree end, enum tree_code cond,
    2087              :                          tree step, location_t loc, gimple_seq *seq1,
    2088              :                          gimple_seq *seq2)
    2089              : {
    2090          944 :   tree tmp;
    2091              : 
    2092              :   /* var = begin. */
    2093          944 :   gimplify_assign (var, begin, seq1);
    2094              : 
    2095              :   /* Loop: for (var = begin; var <cond> end; var += step).  */
    2096          944 :   tree label_loop = create_artificial_label (loc);
    2097          944 :   tree label_cond = create_artificial_label (loc);
    2098              : 
    2099          944 :   gimplify_and_add (fold_build1_loc (loc, GOTO_EXPR, void_type_node,
    2100              :                                      label_cond), seq1);
    2101          944 :   gimple_seq_add_stmt (seq1, gimple_build_label (label_loop));
    2102              : 
    2103              :   /* Everything above is seq1; place loop body here.  */
    2104              : 
    2105              :   /* End of loop body -> put into seq2.  */
    2106          944 :   tmp = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (var), var, step);
    2107          944 :   gimplify_assign (var, tmp, seq2);
    2108          944 :   gimple_seq_add_stmt (seq2, gimple_build_label (label_cond));
    2109          944 :   tmp = fold_build2_loc (loc, cond, boolean_type_node, var, end);
    2110          944 :   tmp = build3_v (COND_EXPR, tmp, build1_v (GOTO_EXPR, label_loop),
    2111              :                   build_empty_stmt (loc));
    2112          944 :   gimplify_and_add (tmp, seq2);
    2113          944 : }
    2114              : 
    2115              : /* Return size variable with the size of an array.  */
    2116              : static tree
    2117          604 : gfc_omp_get_array_size (location_t loc, tree desc, gimple_seq *seq)
    2118              : {
    2119          604 :   tree tmp;
    2120          604 :   gimple_seq seq1 = NULL, seq2 = NULL;
    2121          604 :   tree size = build_decl (loc, VAR_DECL, create_tmp_var_name ("size"),
    2122              :                           size_type_node);
    2123          604 :   tree extent = build_decl (loc, VAR_DECL, create_tmp_var_name ("extent"),
    2124              :                             gfc_array_index_type);
    2125          604 :   tree idx = build_decl (loc, VAR_DECL, create_tmp_var_name ("idx"),
    2126              :                          gfc_array_dim_rank_type);
    2127              : 
    2128          604 :   tree begin = gfc_rank_cst[0];
    2129          604 :   tree end;
    2130          604 :   if (GFC_TYPE_ARRAY_AKIND (TREE_TYPE (desc)) == GFC_ARRAY_ASSUMED_SHAPE_CONT
    2131          604 :       || GFC_TYPE_ARRAY_AKIND (TREE_TYPE (desc)) == GFC_ARRAY_ASSUMED_SHAPE)
    2132            8 :     end = gfc_conv_descriptor_rank_get (desc);
    2133              :   else
    2134          596 :     end = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))];
    2135          604 :   tree step = gfc_rank_cst[1];
    2136              : 
    2137              :   /* size = 0
    2138              :      for (idx = 0; idx < rank; idx++)
    2139              :        extent = gfc->dim[i].ubound - gfc->dim[i].lbound + 1
    2140              :        if (extent < 0) extent = 0
    2141              :          size *= extent.  */
    2142          604 :   gimplify_assign (size, build_int_cst (size_type_node, 1), seq);
    2143              : 
    2144          604 :   gfc_omp_gen_simple_loop (idx, begin, end, LT_EXPR, step, loc, &seq1, &seq2);
    2145          604 :   gimple_seq_add_seq (seq, seq1);
    2146              : 
    2147          604 :   tmp = fold_build2_loc (loc, MINUS_EXPR, gfc_array_index_type,
    2148              :                          gfc_conv_descriptor_ubound_get (desc, idx),
    2149              :                          gfc_conv_descriptor_lbound_get (desc, idx));
    2150          604 :   tmp = fold_build2_loc (loc, PLUS_EXPR, gfc_array_index_type,
    2151              :                          tmp, gfc_index_one_node);
    2152          604 :   gimplify_assign (extent, tmp, seq);
    2153          604 :   tmp = fold_build2_loc (loc, LT_EXPR, boolean_type_node,
    2154              :                          extent, gfc_index_zero_node);
    2155          604 :   tmp = build3_v (COND_EXPR, tmp,
    2156              :                   fold_build2_loc (loc, MODIFY_EXPR,
    2157              :                                    gfc_array_index_type,
    2158              :                                    extent, gfc_index_zero_node),
    2159              :                   build_empty_stmt (loc));
    2160          604 :   gimplify_and_add (tmp, seq);
    2161              :   /* size *= extent.  */
    2162          604 :   gimplify_assign (size, fold_build2_loc (loc, MULT_EXPR, size_type_node, size,
    2163              :                                           fold_convert (size_type_node,
    2164              :                                                         extent)), seq);
    2165          604 :   gimple_seq_add_seq (seq, seq2);
    2166          604 :   return size;
    2167              : }
    2168              : 
    2169              : /* Generate loop to access every array element; takes addr of first element
    2170              :    (decl's data comp); returns loop code in seq1 + seq2
    2171              :    and the pointer to the element as return value.  */
    2172              : static tree
    2173          340 : gfc_omp_elmental_loop (location_t loc, tree decl, tree size, tree elem_len,
    2174              :                        gimple_seq *seq1, gimple_seq *seq2)
    2175              : {
    2176          340 :   tree idx = build_decl (loc, VAR_DECL, create_tmp_var_name ("idx"),
    2177              :                          size_type_node);
    2178          340 :   tree begin = build_zero_cst (size_type_node);
    2179          340 :   tree end = size;
    2180          340 :   tree step = build_int_cst (size_type_node, 1);
    2181          340 :   tree ptr;
    2182              : 
    2183          340 :   gfc_omp_gen_simple_loop (idx, begin, end, LT_EXPR, step, loc, seq1, seq2);
    2184              : 
    2185          340 :   tree type = TREE_TYPE (decl);
    2186          340 :   if (POINTER_TYPE_P (type))
    2187              :     {
    2188          296 :       type = TREE_TYPE (type);
    2189          296 :       gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
    2190          296 :       decl = fold_convert (build_pointer_type (TREE_TYPE (type)), decl);
    2191              :     }
    2192              :   else
    2193              :     {
    2194           44 :       gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
    2195           44 :       decl = build_fold_addr_expr_loc (loc, decl);
    2196              :     }
    2197          340 :   decl = fold_convert (build_pointer_type (TREE_TYPE (type)), decl);
    2198          340 :   tree tmp = build2_loc (loc, MULT_EXPR, size_type_node, idx,
    2199              :                          fold_convert (size_type_node, elem_len));
    2200          340 :   ptr = build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (decl), decl, tmp);
    2201          340 :   gimple_seq seq3 = NULL;
    2202          340 :   ptr = force_gimple_operand (ptr, &seq3, true, NULL_TREE);
    2203          340 :   gimple_seq_add_seq (seq1, seq3);
    2204              : 
    2205          340 :   return ptr;
    2206              : }
    2207              : 
    2208              : 
    2209              : /* If do_copy, copy data pointer and vptr (if applicable) as well.
    2210              :    Otherwise, only handle allocatable components.
    2211              :    do_copy == false can happen only with nonpolymorphic arguments
    2212              :    to a copy clause.
    2213              :    if (is_cnt) token ... offset is ignored and num is used, otherwise
    2214              :    num is NULL_TREE and unused.  */
    2215              : 
    2216              : static void
    2217         1696 : gfc_omp_deep_mapping_item (bool is_cnt, bool do_copy, bool do_alloc_check,
    2218              :                            location_t loc, tree decl, tree *token,
    2219              :                            unsigned HOST_WIDE_INT tkind, tree data_array,
    2220              :                            tree sizes_array, tree kinds_array, tree offset_data,
    2221              :                            tree offset, tree num, gimple_seq *seq,
    2222              :                            const gimple *ctx, bool *poly_warned)
    2223              : {
    2224         1696 :   tree tmp;
    2225         1696 :   tree type = TREE_TYPE (decl);
    2226         1696 :   if (POINTER_TYPE_P (type))
    2227          416 :     type = TREE_TYPE (type);
    2228         1696 :   tree end_label = NULL_TREE;
    2229         1696 :   tree size = NULL_TREE, elem_len = NULL_TREE;
    2230              : 
    2231         1696 :   bool poly = gfc_is_polymorphic_nonptr (type);
    2232         1696 :   if (poly && is_cnt && !*poly_warned)
    2233              :     {
    2234           41 :       if (gfc_is_unlimited_polymorphic_nonptr (type))
    2235            2 :         error_at (loc,
    2236              :                   "Mapping of unlimited polymorphic list item %qD is "
    2237              :                   "unspecified behavior and unsupported", decl);
    2238              : 
    2239              :       else
    2240           39 :         warning_at (loc, OPT_Wopenmp,
    2241              :                     "Mapping of polymorphic list item %qD is "
    2242              :                     "unspecified behavior", decl);
    2243           41 :       *poly_warned = true;
    2244              :     }
    2245         1696 :   if (do_alloc_check)
    2246              :     {
    2247         1428 :       tree then_label = create_artificial_label (loc);
    2248         1428 :       end_label = create_artificial_label (loc);
    2249         1428 :       tmp = decl;
    2250         1428 :       if (TREE_CODE (TREE_TYPE (tmp)) == REFERENCE_TYPE
    2251         1428 :           || (POINTER_TYPE_P (TREE_TYPE (tmp))
    2252          396 :               && (POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (tmp)))
    2253          396 :                   || GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (tmp))))))
    2254            8 :         tmp = build_fold_indirect_ref_loc (loc, tmp);
    2255         1428 :       if (poly)
    2256          242 :         tmp = gfc_class_data_get (tmp);
    2257         1428 :       if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)))
    2258          904 :         tmp = gfc_conv_descriptor_data_get (tmp);
    2259         1428 :       gimple_seq seq2 = NULL;
    2260         1428 :       tmp = force_gimple_operand (tmp, &seq2, true, NULL_TREE);
    2261         1428 :       gimple_seq_add_seq (seq, seq2);
    2262              : 
    2263         1428 :       gimple_seq_add_stmt (seq,
    2264         1428 :                            gimple_build_cond (NE_EXPR, tmp, null_pointer_node,
    2265              :                                               then_label, end_label));
    2266         1428 :       gimple_seq_add_stmt (seq, gimple_build_label (then_label));
    2267              :     }
    2268         1696 :   tree class_decl = decl;
    2269         1696 :   if (poly)
    2270              :     {
    2271          242 :       decl = gfc_class_data_get (decl);
    2272          242 :       type = TREE_TYPE (decl);
    2273              :     }
    2274         1696 :   if (POINTER_TYPE_P (TREE_TYPE (decl)))
    2275              :     {
    2276          548 :       decl = build_fold_indirect_ref (decl);
    2277          548 :       type = TREE_TYPE (decl);
    2278              :     }
    2279              : 
    2280         1696 :   if (is_cnt && do_copy)
    2281              :     {
    2282          645 :       tree tmp = fold_build2_loc (loc, PLUS_EXPR, size_type_node,
    2283              :                                   num, build_int_cst (size_type_node, 1));
    2284          645 :       gimplify_assign (num, tmp, seq);
    2285              :     }
    2286         1051 :   else if (do_copy)
    2287              :     {
    2288              :       /* copy data pointer  */
    2289          645 :       tree bytesize;
    2290          645 :       if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
    2291              :         {
    2292              :           /* TODO: Optimization: Shouldn't this be an expr. const, except for
    2293              :              deferred-length strings. (Cf. also below).  */
    2294          440 :           elem_len = (poly ? gfc_class_vtab_size_get (class_decl)
    2295          385 :                            : gfc_conv_descriptor_elem_len_get (decl));
    2296          880 :           tmp = (POINTER_TYPE_P (TREE_TYPE (decl))
    2297          440 :                  ? build_fold_indirect_ref (decl) : decl);
    2298          440 :           size = gfc_omp_get_array_size (loc, tmp, seq);
    2299          440 :           bytesize = fold_build2_loc (loc, MULT_EXPR, size_type_node,
    2300              :                                       fold_convert (size_type_node, size),
    2301              :                                       fold_convert (size_type_node, elem_len));
    2302          440 :           tmp = gfc_conv_descriptor_data_get (decl);
    2303              :         }
    2304          205 :       else if (poly)
    2305              :         {
    2306           66 :           tmp = decl;
    2307           66 :           bytesize = fold_convert (size_type_node,
    2308              :                                    gfc_class_vtab_size_get (class_decl));
    2309              :         }
    2310              :       else
    2311              :         {
    2312          139 :           tmp = decl;
    2313          139 :           bytesize = TYPE_SIZE_UNIT (TREE_TYPE (decl));
    2314              :         }
    2315          645 :       unsigned HOST_WIDE_INT tkind2 = tkind;
    2316          645 :       if (!is_cnt
    2317          645 :           && (tkind == GOMP_MAP_ALLOC
    2318          617 :               || (tkind == GOMP_MAP_FROM
    2319           60 :                   && (gimple_omp_target_kind (ctx)
    2320              :                       != GF_OMP_TARGET_KIND_EXIT_DATA)))
    2321          689 :           && gfc_omp_replace_alloc_by_to_mapping (TREE_TYPE (decl), decl, true))
    2322           12 :         tkind2 = tkind == GOMP_MAP_ALLOC ? GOMP_MAP_TO : GOMP_MAP_TOFROM;
    2323              : 
    2324          645 :       gfc_omp_deep_mapping_map (tmp, bytesize, tkind2, loc, data_array,
    2325              :                                 sizes_array, kinds_array, offset_data,
    2326              :                                 offset, seq, ctx);
    2327              :     }
    2328              : 
    2329         1696 :   tmp = decl;
    2330         1696 :   if (POINTER_TYPE_P (TREE_TYPE (decl)))
    2331            0 :     while (TREE_CODE (tmp) == COMPONENT_REF || TREE_CODE (tmp) == ARRAY_REF)
    2332            0 :       tmp = TREE_OPERAND (tmp, TREE_CODE (tmp) == COMPONENT_REF ? 1 : 0);
    2333         1696 :   if (poly || gfc_has_alloc_comps (type, tmp, true))
    2334              :     {
    2335          862 :       gimple_seq seq2 = NULL;
    2336          862 :       if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
    2337              :         {
    2338          296 :           if (elem_len == NULL_TREE)
    2339              :             {
    2340          164 :               elem_len = gfc_conv_descriptor_elem_len_get (decl);
    2341          164 :               size = fold_convert (size_type_node,
    2342              :                                    gfc_omp_get_array_size (loc, decl, seq));
    2343              :             }
    2344          296 :           decl = gfc_conv_descriptor_data_get (decl);
    2345          296 :           decl = gfc_omp_elmental_loop (loc, decl, size, elem_len, seq, &seq2);
    2346          296 :           decl = build_fold_indirect_ref_loc (loc, decl);
    2347              :         }
    2348          566 :       else if (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE)
    2349              :         {
    2350           44 :           type = TREE_TYPE (tmp);
    2351              :           /* FIXME: PR95868 - for var%str of deferred length, elem_len == 0;
    2352              :              len is stored as var%_str_length, but not in GFC_DECL_STRING_LEN
    2353              :              nor in TYPE_SIZE_UNIT as expression. */
    2354           44 :           elem_len = TYPE_SIZE_UNIT (TREE_TYPE (type));
    2355           44 :           size = fold_convert (size_type_node, GFC_TYPE_ARRAY_SIZE (type));
    2356           44 :           decl = gfc_omp_elmental_loop (loc, decl, size, elem_len, seq, &seq2);
    2357           44 :           decl = build_fold_indirect_ref_loc (loc, decl);
    2358              :         }
    2359          522 :       else if (POINTER_TYPE_P (TREE_TYPE (decl)))
    2360            0 :         decl = build_fold_indirect_ref (decl);
    2361              : 
    2362          862 :       gfc_omp_deep_mapping_comps (is_cnt, loc, decl, token, tkind,
    2363              :                                   data_array, sizes_array, kinds_array,
    2364              :                                   offset_data, offset, num, seq, ctx,
    2365              :                                   poly_warned);
    2366          862 :       gimple_seq_add_seq (seq, seq2);
    2367              :     }
    2368         1696 :   if (end_label)
    2369         1428 :     gimple_seq_add_stmt (seq, gimple_build_label (end_label));
    2370         1696 : }
    2371              : 
    2372              : 
    2373              : /* Which map types to check/handle for deep mapping.  */
    2374              : static bool
    2375        42329 : gfc_omp_deep_map_kind_p (tree clause)
    2376              : {
    2377        42329 :   switch (OMP_CLAUSE_CODE (clause))
    2378              :     {
    2379        38745 :     case OMP_CLAUSE_MAP:
    2380        38745 :       break;
    2381              :     case OMP_CLAUSE_FIRSTPRIVATE:
    2382              :     case OMP_CLAUSE_TO:
    2383              :     case OMP_CLAUSE_FROM:
    2384              :       return true;
    2385            0 :     default:
    2386            0 :       gcc_unreachable ();
    2387              :     }
    2388              : 
    2389        38745 :   switch (OMP_CLAUSE_MAP_KIND (clause))
    2390              :     {
    2391              :     case GOMP_MAP_TO:
    2392              :     case GOMP_MAP_FROM:
    2393              :     case GOMP_MAP_TOFROM:
    2394              :     case GOMP_MAP_ALWAYS_TO:
    2395              :     case GOMP_MAP_ALWAYS_FROM:
    2396              :     case GOMP_MAP_ALWAYS_TOFROM:
    2397              :     case GOMP_MAP_ALWAYS_PRESENT_FROM:
    2398              :     case GOMP_MAP_ALWAYS_PRESENT_TO:
    2399              :     case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
    2400              :     case GOMP_MAP_FIRSTPRIVATE:
    2401              :     case GOMP_MAP_ALLOC:
    2402              :       return true;
    2403              :     case GOMP_MAP_POINTER:
    2404              :     case GOMP_MAP_TO_PSET:
    2405              :     case GOMP_MAP_FORCE_PRESENT:
    2406              :     case GOMP_MAP_DELETE:
    2407              :     case GOMP_MAP_FORCE_DEVICEPTR:
    2408              :     case GOMP_MAP_DEVICE_RESIDENT:
    2409              :     case GOMP_MAP_LINK:
    2410              :     case GOMP_MAP_IF_PRESENT:
    2411              :     case GOMP_MAP_PRESENT_ALLOC:
    2412              :     case GOMP_MAP_PRESENT_FROM:
    2413              :     case GOMP_MAP_PRESENT_TO:
    2414              :     case GOMP_MAP_PRESENT_TOFROM:
    2415              :     case GOMP_MAP_FIRSTPRIVATE_INT:
    2416              :     case GOMP_MAP_USE_DEVICE_PTR:
    2417              :     case GOMP_MAP_ZERO_LEN_ARRAY_SECTION:
    2418              :     case GOMP_MAP_FORCE_ALLOC:
    2419              :     case GOMP_MAP_FORCE_TO:
    2420              :     case GOMP_MAP_FORCE_FROM:
    2421              :     case GOMP_MAP_FORCE_TOFROM:
    2422              :     case GOMP_MAP_USE_DEVICE_PTR_IF_PRESENT:
    2423              :     case GOMP_MAP_STRUCT:
    2424              :     case GOMP_MAP_STRUCT_UNORD:
    2425              :     case GOMP_MAP_ALWAYS_POINTER:
    2426              :     case GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION:
    2427              :     case GOMP_MAP_DELETE_ZERO_LEN_ARRAY_SECTION:
    2428              :     case GOMP_MAP_RELEASE:
    2429              :     case GOMP_MAP_ATTACH:
    2430              :     case GOMP_MAP_DETACH:
    2431              :     case GOMP_MAP_FORCE_DETACH:
    2432              :     case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
    2433              :     case GOMP_MAP_FIRSTPRIVATE_POINTER:
    2434              :     case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
    2435              :     case GOMP_MAP_ATTACH_DETACH:
    2436              :       break;
    2437            0 :     default:
    2438            0 :       gcc_unreachable ();
    2439              :     }
    2440              :   return false;
    2441              : }
    2442              : 
    2443              : /* Three OpenMP deep-mapping lang hooks: gfc_omp_deep_mapping{_p,_cnt,}.  */
    2444              : 
    2445              : /* Common check for gfc_omp_deep_mapping_p and gfc_omp_deep_mapping_do. */
    2446              : 
    2447              : static tree
    2448        93928 : gfc_omp_deep_mapping_int_p (const gimple *ctx, tree clause)
    2449              : {
    2450        93928 :   if (is_gimple_omp_oacc (ctx) || !gfc_omp_deep_map_kind_p (clause))
    2451              :     return NULL_TREE;
    2452        22426 :   tree decl = OMP_CLAUSE_DECL (clause);
    2453        22426 :   if (OMP_CLAUSE_SIZE (clause) != NULL_TREE
    2454        22356 :       && DECL_P (OMP_CLAUSE_SIZE (clause))
    2455         6578 :       && DECL_LANG_SPECIFIC (OMP_CLAUSE_SIZE (clause))
    2456        22725 :       && GFC_DECL_SAVED_DESCRIPTOR (OMP_CLAUSE_SIZE (clause)))
    2457              :     /* Saved decl. */
    2458          299 :     decl = GFC_DECL_SAVED_DESCRIPTOR (OMP_CLAUSE_SIZE (clause));
    2459        22127 :   else if (TREE_CODE (decl) == MEM_REF || TREE_CODE (decl) == INDIRECT_REF)
    2460              :     /* The following can happen for, e.g., class(t) :: var(..)  */
    2461        12515 :     decl = TREE_OPERAND (decl, 0);
    2462        22426 :   if (TREE_CODE (decl) == INDIRECT_REF)
    2463              :     /* The following can happen for, e.g., class(t) :: var(..)  */
    2464          132 :     decl = TREE_OPERAND (decl, 0);
    2465        22426 :   if (DECL_P (decl)
    2466        13564 :       && DECL_LANG_SPECIFIC (decl)
    2467        24594 :       && GFC_DECL_SAVED_DESCRIPTOR (decl))
    2468           74 :     decl = GFC_DECL_SAVED_DESCRIPTOR (decl);
    2469              :   /* Handle map(to: var.desc) map([to/from/tofrom:] var.desc.data)
    2470              :      to get proper map kind by skipping to the next item. */
    2471        22426 :   tree tmp = OMP_CLAUSE_CHAIN (clause);
    2472        22426 :   if (tmp != NULL_TREE
    2473        16706 :       && OMP_CLAUSE_CODE (tmp) == OMP_CLAUSE_CODE (clause)
    2474        15048 :       && OMP_CLAUSE_SIZE (tmp) != NULL_TREE
    2475        15048 :       && DECL_P (OMP_CLAUSE_SIZE (tmp))
    2476         1496 :       && DECL_LANG_SPECIFIC (OMP_CLAUSE_SIZE (tmp))
    2477        22498 :       && GFC_DECL_SAVED_DESCRIPTOR (OMP_CLAUSE_SIZE (tmp)) == decl)
    2478              :     return NULL_TREE;
    2479        22426 :   if (DECL_P (decl)
    2480        13564 :       && DECL_LANG_SPECIFIC (decl)
    2481        24549 :       && GFC_DECL_SAVED_DESCRIPTOR (decl))
    2482           29 :     decl = GFC_DECL_SAVED_DESCRIPTOR (decl);
    2483        22426 :   tree type = TREE_TYPE (decl);
    2484        22426 :   if (POINTER_TYPE_P (type))
    2485        13445 :     type = TREE_TYPE (type);
    2486        22426 :   if (POINTER_TYPE_P (type))
    2487          140 :     type = TREE_TYPE (type);
    2488        22426 :   tmp = decl;
    2489        24188 :   while (TREE_CODE (tmp) == COMPONENT_REF || TREE_CODE (tmp) == ARRAY_REF)
    2490         2423 :     tmp = TREE_OPERAND (tmp, TREE_CODE (tmp) == COMPONENT_REF ? 1 : 0);
    2491        22426 :   if (!gfc_is_polymorphic_nonptr (type)
    2492        22426 :       && !gfc_has_alloc_comps (type, tmp, true))
    2493              :     return NULL_TREE;
    2494              :   return decl;
    2495              : }
    2496              : 
    2497              : /* Return true if there is any deep mapping required, even if the number of
    2498              :    mappings is known at compile time.  Deep mapping is required if the passed
    2499              :    CLAUSE is a map clause and its OMP_CLAUSE_DECL refers to a derived-type with
    2500              :    allocatable components. CTX is the statement that contains the CLAUSE.  */
    2501              : 
    2502              : bool
    2503        45472 : gfc_omp_deep_mapping_p (const gimple *ctx, tree clause)
    2504              : {
    2505        45472 :   tree decl = gfc_omp_deep_mapping_int_p (ctx, clause);
    2506        45472 :   if (decl == NULL_TREE)
    2507        45328 :     return false;
    2508              :   return true;
    2509              : }
    2510              : 
    2511              : /* Handle gfc_omp_deep_mapping{,_cnt} */
    2512              : static tree
    2513        48432 : gfc_omp_deep_mapping_do (bool is_cnt, const gimple *ctx, tree clause,
    2514              :                          unsigned HOST_WIDE_INT tkind, tree data, tree sizes,
    2515              :                          tree kinds, tree offset_data, tree offset,
    2516              :                          gimple_seq *seq)
    2517              : {
    2518        48432 :   tree num = NULL_TREE;
    2519        48432 :   location_t loc = OMP_CLAUSE_LOCATION (clause);
    2520        48432 :   tree decl = gfc_omp_deep_mapping_int_p (ctx, clause);
    2521        48432 :   bool poly_warned = false;
    2522        48432 :   if (decl == NULL_TREE)
    2523              :     return NULL_TREE;
    2524              :   /* Handle: map(alloc:dt%cmp [len: ptr_size]) map(tofrom: D.0123...),
    2525              :      where GFC_DECL_SAVED_DESCRIPTOR(D.0123) is the same (here: dt%cmp).  */
    2526          418 :   if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_MAP
    2527          418 :       && (OMP_CLAUSE_MAP_KIND (clause) == GOMP_MAP_ALLOC
    2528          374 :           || OMP_CLAUSE_MAP_KIND (clause) == GOMP_MAP_PRESENT_ALLOC))
    2529              :     {
    2530              :       tree c = clause;
    2531           84 :       while ((c = OMP_CLAUSE_CHAIN (c)) != NULL_TREE)
    2532              :         {
    2533           60 :           if (!gfc_omp_deep_map_kind_p (c))
    2534           36 :             continue;
    2535           24 :           tree d = gfc_omp_deep_mapping_int_p (ctx, c);
    2536           24 :           if (d != NULL_TREE && operand_equal_p (decl, d, 0))
    2537              :             return NULL_TREE;
    2538              :         }
    2539              :     }
    2540          406 :   tree type = TREE_TYPE (decl);
    2541          406 :   if (POINTER_TYPE_P (type))
    2542          138 :     type = TREE_TYPE (type);
    2543          406 :   if (POINTER_TYPE_P (type))
    2544            8 :     type = TREE_TYPE (type);
    2545          406 :   bool poly = gfc_is_polymorphic_nonptr (type);
    2546              : 
    2547          406 :   if (is_cnt)
    2548              :     {
    2549          203 :       num = build_decl (loc, VAR_DECL,
    2550              :                         create_tmp_var_name ("n_deepmap"), size_type_node);
    2551          203 :       tree tmp = fold_build2_loc (loc, MODIFY_EXPR, size_type_node, num,
    2552              :                                   build_int_cst (size_type_node, 0));
    2553          203 :       gimple_add_tmp_var (num);
    2554          203 :       gimplify_and_add (tmp, seq);
    2555              :     }
    2556              :   else
    2557          203 :     gcc_assert (short_unsigned_type_node == TREE_TYPE (TREE_TYPE (kinds)));
    2558              : 
    2559          406 :   bool do_copy = poly;
    2560          406 :   bool do_alloc_check = false;
    2561          406 :   tree token = NULL_TREE;
    2562          406 :   tree tmp = decl;
    2563          406 :   if (poly)
    2564              :     {
    2565           40 :       tmp = TYPE_FIELDS (type);
    2566           40 :       type = TREE_TYPE (tmp);
    2567              :     }
    2568              :   else
    2569          418 :     while (TREE_CODE (tmp) == COMPONENT_REF || TREE_CODE (tmp) == ARRAY_REF)
    2570           72 :       tmp = TREE_OPERAND (tmp, TREE_CODE (tmp) == COMPONENT_REF ? 1 : 0);
    2571          406 :   if (TREE_CODE (tmp) == MEM_REF)
    2572           16 :     tmp = TREE_OPERAND (tmp, 0);
    2573          406 :   if (TREE_CODE (tmp) == SSA_NAME)
    2574              :     {
    2575           16 :       gimple *def_stmt = SSA_NAME_DEF_STMT (tmp);
    2576           16 :       if (gimple_code (def_stmt) == GIMPLE_ASSIGN)
    2577              :         {
    2578           16 :           tmp = gimple_assign_rhs1 (def_stmt);
    2579           16 :           if (poly)
    2580              :             {
    2581            0 :               tmp = TYPE_FIELDS (type);
    2582            0 :               type = TREE_TYPE (tmp);
    2583              :             }
    2584              :           else
    2585           32 :             while (TREE_CODE (tmp) == COMPONENT_REF
    2586           32 :                    || TREE_CODE (tmp) == ARRAY_REF)
    2587           16 :               tmp = TREE_OPERAND (tmp,
    2588              :                                   TREE_CODE (tmp) == COMPONENT_REF ? 1 : 0);
    2589              :         }
    2590              :     }
    2591              :   /* If the clause argument is nonallocatable, skip is-allocate check. */
    2592          406 :   if (GFC_DECL_GET_SCALAR_ALLOCATABLE (tmp)
    2593          278 :       || GFC_DECL_GET_SCALAR_POINTER (tmp)
    2594          420 :       || (GFC_DESCRIPTOR_TYPE_P (type)
    2595           42 :           && (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE
    2596           24 :               || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER
    2597            8 :               || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT)))
    2598              :     do_alloc_check = true;
    2599              : 
    2600          406 :   if (!is_cnt
    2601          203 :       && OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_MAP
    2602          199 :       && (tkind == GOMP_MAP_ALLOC
    2603          187 :           || (tkind == GOMP_MAP_FROM
    2604           21 :               && (gimple_omp_target_kind (ctx)
    2605              :                   != GF_OMP_TARGET_KIND_EXIT_DATA)))
    2606          442 :       && (poly || gfc_omp_replace_alloc_by_to_mapping (type, tmp, true)))
    2607           24 :     OMP_CLAUSE_SET_MAP_KIND (clause, tkind == GOMP_MAP_ALLOC ? GOMP_MAP_TO
    2608              :                                                              : GOMP_MAP_TOFROM);
    2609              : 
    2610              :   /* TODO: For map(a(:)), we know it is present & allocated.  */
    2611              : 
    2612          406 :   tree present = (DECL_P (decl) ? gfc_omp_check_optional_argument (decl, true)
    2613              :                                 : NULL_TREE);
    2614          690 :   if (POINTER_TYPE_P (TREE_TYPE (decl))
    2615          422 :       && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
    2616            8 :     decl = build_fold_indirect_ref (decl);
    2617          406 :   if (present)
    2618              :     {
    2619           16 :       tree then_label = create_artificial_label (loc);
    2620           16 :       tree end_label = create_artificial_label (loc);
    2621           16 :       gimple_seq seq2 = NULL;
    2622           16 :       tmp = force_gimple_operand (present, &seq2, true, NULL_TREE);
    2623           16 :       gimple_seq_add_seq (seq, seq2);
    2624           16 :       gimple_seq_add_stmt (seq,
    2625           16 :                            gimple_build_cond_from_tree (present,
    2626              :                                                         then_label, end_label));
    2627           16 :       gimple_seq_add_stmt (seq, gimple_build_label (then_label));
    2628           16 :       gfc_omp_deep_mapping_item (is_cnt, do_copy, do_alloc_check, loc, decl,
    2629              :                                  &token, tkind, data, sizes, kinds,
    2630              :                                  offset_data, offset, num, seq, ctx,
    2631              :                                  &poly_warned);
    2632           16 :       gimple_seq_add_stmt (seq, gimple_build_label (end_label));
    2633              :     }
    2634              :   else
    2635          390 :     gfc_omp_deep_mapping_item (is_cnt, do_copy, do_alloc_check, loc, decl,
    2636              :                                &token, tkind, data, sizes, kinds, offset_data,
    2637              :                                offset, num, seq, ctx, &poly_warned);
    2638              :   /* Multiply by 2 as there are two mappings: data + pointer assign.  */
    2639          406 :   if (is_cnt)
    2640          203 :     gimplify_assign (num,
    2641              :                      fold_build2_loc (loc, MULT_EXPR,
    2642              :                                       size_type_node, num,
    2643              :                                       build_int_cst (size_type_node, 2)), seq);
    2644              :   return num;
    2645              : }
    2646              : 
    2647              : /* Returns NULL_TREE if known that no deep mapping is required for the passed
    2648              :    'map' CLAUSE, otherwise returns a size_type expression with the number of
    2649              :    required data-mapping operations, which may be zero.  Deep mapping is
    2650              :    required for allocatable components of derived types; the number of mapping
    2651              :    operations depends on the allocation status, array sizes and the dynamic
    2652              :    type.  CTX is the gimple statement that contains the map CLAUSE; the
    2653              :    gimple code used for counting is added to SEQ.  */
    2654              : 
    2655              : tree
    2656        48004 : gfc_omp_deep_mapping_cnt (const gimple *ctx, tree clause, gimple_seq *seq)
    2657              : {
    2658        48004 :   return gfc_omp_deep_mapping_do (true, ctx, clause, 0, NULL_TREE, NULL_TREE,
    2659        48004 :                                   NULL_TREE, NULL_TREE, NULL_TREE, seq);
    2660              : }
    2661              : 
    2662              : /* Handle the deep mapping for the passed map CLAUSE that is part of
    2663              :    the gimple statement CTX by walking all allocated allocatable components
    2664              :    and its allocatable components to add additional data-mapping operations.
    2665              :    TKIND is the map-type/kind to be used. The generated code is added to
    2666              :    SEQ – and the actual struct-field address used for mapping, the map size,
    2667              :    and kind value to the arrays DATA, SIZES, and KINDS, respectively.
    2668              :    OFFSET_DATA and OFFSET are size-type variables; the map operations are
    2669              :    added at array index OFFSET_DATA for DATA and at array index OFFSET for
    2670              :    SIZES/KINDS, incrementing the offsets after each assignment.  */
    2671              : 
    2672              : void
    2673          428 : gfc_omp_deep_mapping (const gimple *ctx, tree clause,
    2674              :                       unsigned HOST_WIDE_INT tkind, tree data,
    2675              :                       tree sizes, tree kinds, tree offset_data, tree offset,
    2676              :                       gimple_seq *seq)
    2677              : {
    2678          428 :   (void) gfc_omp_deep_mapping_do (false, ctx, clause, tkind, data, sizes, kinds,
    2679              :                                   offset_data, offset, seq);
    2680          428 : }
    2681              : 
    2682              : /* Return true if DECL is a scalar variable (for the purpose of
    2683              :    implicit firstprivatization/mapping). Only if 'ptr_alloc_ok.'
    2684              :    is true, allocatables and pointers are permitted. */
    2685              : 
    2686              : bool
    2687         4072 : gfc_omp_scalar_p (tree decl, bool ptr_alloc_ok)
    2688              : {
    2689         4072 :   tree type = TREE_TYPE (decl);
    2690         4072 :   if (TREE_CODE (type) == REFERENCE_TYPE)
    2691         1360 :     type = TREE_TYPE (type);
    2692         4072 :   if (TREE_CODE (type) == POINTER_TYPE)
    2693              :     {
    2694          593 :       if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
    2695          593 :           || GFC_DECL_GET_SCALAR_POINTER (decl))
    2696              :         {
    2697          148 :           if (!ptr_alloc_ok)
    2698              :             return false;
    2699            0 :           type = TREE_TYPE (type);
    2700              :         }
    2701          445 :       if (GFC_ARRAY_TYPE_P (type)
    2702          445 :           || GFC_CLASS_TYPE_P (type))
    2703              :         return false;
    2704              :     }
    2705         3500 :   if ((TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == INTEGER_TYPE)
    2706         6320 :       && TYPE_STRING_FLAG (type))
    2707              :     return false;
    2708         3594 :   if (INTEGRAL_TYPE_P (type)
    2709         3594 :       || SCALAR_FLOAT_TYPE_P (type)
    2710         3594 :       || COMPLEX_FLOAT_TYPE_P (type))
    2711         2996 :     return true;
    2712              :   return false;
    2713              : }
    2714              : 
    2715              : 
    2716              : /* Return true if DECL is a scalar with target attribute but does not have the
    2717              :    allocatable (or pointer) attribute (for the purpose of implicit mapping).  */
    2718              : 
    2719              : bool
    2720         3964 : gfc_omp_scalar_target_p (tree decl)
    2721              : {
    2722         3964 :   return (DECL_P (decl) && GFC_DECL_GET_SCALAR_TARGET (decl)
    2723         4065 :           && gfc_omp_scalar_p (decl, false));
    2724              : }
    2725              : 
    2726              : 
    2727              : /* Return true if DECL's DECL_VALUE_EXPR (if any) should be
    2728              :    disregarded in OpenMP construct, because it is going to be
    2729              :    remapped during OpenMP lowering.  SHARED is true if DECL
    2730              :    is going to be shared, false if it is going to be privatized.  */
    2731              : 
    2732              : bool
    2733      1703109 : gfc_omp_disregard_value_expr (tree decl, bool shared)
    2734              : {
    2735      1703109 :   if (GFC_DECL_COMMON_OR_EQUIV (decl)
    2736      1703109 :       && DECL_HAS_VALUE_EXPR_P (decl))
    2737              :     {
    2738         3030 :       tree value = DECL_VALUE_EXPR (decl);
    2739              : 
    2740         3030 :       if (TREE_CODE (value) == COMPONENT_REF
    2741         3030 :           && VAR_P (TREE_OPERAND (value, 0))
    2742         6060 :           && GFC_DECL_COMMON_OR_EQUIV (TREE_OPERAND (value, 0)))
    2743              :         {
    2744              :           /* If variable in COMMON or EQUIVALENCE is privatized, return
    2745              :              true, as just that variable is supposed to be privatized,
    2746              :              not the whole COMMON or whole EQUIVALENCE.
    2747              :              For shared variables in COMMON or EQUIVALENCE, let them be
    2748              :              gimplified to DECL_VALUE_EXPR, so that for multiple shared vars
    2749              :              from the same COMMON or EQUIVALENCE just one sharing of the
    2750              :              whole COMMON or EQUIVALENCE is enough.  */
    2751         3030 :           return ! shared;
    2752              :         }
    2753              :     }
    2754              : 
    2755      1700079 :   if (GFC_DECL_RESULT (decl) && DECL_HAS_VALUE_EXPR_P (decl))
    2756          334 :     return ! shared;
    2757              : 
    2758              :   return false;
    2759              : }
    2760              : 
    2761              : /* Return true if DECL that is shared iff SHARED is true should
    2762              :    be put into OMP_CLAUSE_PRIVATE with OMP_CLAUSE_PRIVATE_DEBUG
    2763              :    flag set.  */
    2764              : 
    2765              : bool
    2766        39027 : gfc_omp_private_debug_clause (tree decl, bool shared)
    2767              : {
    2768        39027 :   if (GFC_DECL_CRAY_POINTEE (decl))
    2769              :     return true;
    2770              : 
    2771        38991 :   if (GFC_DECL_COMMON_OR_EQUIV (decl)
    2772        38991 :       && DECL_HAS_VALUE_EXPR_P (decl))
    2773              :     {
    2774          326 :       tree value = DECL_VALUE_EXPR (decl);
    2775              : 
    2776          326 :       if (TREE_CODE (value) == COMPONENT_REF
    2777          326 :           && VAR_P (TREE_OPERAND (value, 0))
    2778          652 :           && GFC_DECL_COMMON_OR_EQUIV (TREE_OPERAND (value, 0)))
    2779              :         return shared;
    2780              :     }
    2781              : 
    2782              :   return false;
    2783              : }
    2784              : 
    2785              : /* Register language specific type size variables as potentially OpenMP
    2786              :    firstprivate variables.  */
    2787              : 
    2788              : void
    2789        22362 : gfc_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *ctx, tree type)
    2790              : {
    2791        22362 :   if (GFC_ARRAY_TYPE_P (type) || GFC_DESCRIPTOR_TYPE_P (type))
    2792              :     {
    2793         4007 :       int r;
    2794              : 
    2795         4007 :       gcc_assert (TYPE_LANG_SPECIFIC (type) != NULL);
    2796         9216 :       for (r = 0; r < GFC_TYPE_ARRAY_RANK (type); r++)
    2797              :         {
    2798         5209 :           omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_LBOUND (type, r));
    2799         5209 :           omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_UBOUND (type, r));
    2800         5209 :           omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_STRIDE (type, r));
    2801              :         }
    2802         4007 :       omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_SIZE (type));
    2803         4007 :       omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_OFFSET (type));
    2804              :     }
    2805        22362 : }
    2806              : 
    2807              : 
    2808              : static inline tree
    2809        76597 : gfc_trans_add_clause (tree node, tree tail)
    2810              : {
    2811        76597 :   OMP_CLAUSE_CHAIN (node) = tail;
    2812        76597 :   return node;
    2813              : }
    2814              : 
    2815              : static tree
    2816        43928 : gfc_trans_omp_variable (gfc_symbol *sym, bool declare_simd)
    2817              : {
    2818        43928 :   if (declare_simd)
    2819              :     {
    2820          182 :       int cnt = 0;
    2821          182 :       gfc_symbol *proc_sym;
    2822          182 :       gfc_formal_arglist *f;
    2823              : 
    2824          182 :       gcc_assert (sym->attr.dummy);
    2825          182 :       proc_sym = sym->ns->proc_name;
    2826          182 :       if (proc_sym->attr.entry_master)
    2827            0 :         ++cnt;
    2828          182 :       if (gfc_return_by_reference (proc_sym))
    2829              :         {
    2830            0 :           ++cnt;
    2831            0 :           if (proc_sym->ts.type == BT_CHARACTER)
    2832            0 :             ++cnt;
    2833              :         }
    2834          349 :       for (f = gfc_sym_get_dummy_args (proc_sym); f; f = f->next)
    2835          349 :         if (f->sym == sym)
    2836              :           break;
    2837          167 :         else if (f->sym)
    2838          167 :           ++cnt;
    2839          182 :       gcc_assert (f);
    2840          182 :       return build_int_cst (integer_type_node, cnt);
    2841              :     }
    2842              : 
    2843        43746 :   tree t = gfc_get_symbol_decl (sym);
    2844        43746 :   tree parent_decl;
    2845        43746 :   int parent_flag;
    2846        43746 :   bool return_value;
    2847        43746 :   bool alternate_entry;
    2848        43746 :   bool entry_master;
    2849              : 
    2850        43746 :   return_value = sym->attr.function && sym->result == sym;
    2851          167 :   alternate_entry = sym->attr.function && sym->attr.entry
    2852        43780 :                     && sym->result == sym;
    2853        87492 :   entry_master = sym->attr.result
    2854          172 :                  && sym->ns->proc_name->attr.entry_master
    2855        43758 :                  && !gfc_return_by_reference (sym->ns->proc_name);
    2856        43746 :   parent_decl = current_function_decl
    2857        43746 :                 ? DECL_CONTEXT (current_function_decl) : NULL_TREE;
    2858              : 
    2859        43746 :   if ((t == parent_decl && return_value)
    2860        43739 :        || (sym->ns && sym->ns->proc_name
    2861        43739 :            && sym->ns->proc_name->backend_decl == parent_decl
    2862         2174 :            && (alternate_entry || entry_master)))
    2863              :     parent_flag = 1;
    2864              :   else
    2865        43737 :     parent_flag = 0;
    2866              : 
    2867              :   /* Special case for assigning the return value of a function.
    2868              :      Self recursive functions must have an explicit return value.  */
    2869        43746 :   if (return_value && (t == current_function_decl || parent_flag))
    2870           97 :     t = gfc_get_fake_result_decl (sym, parent_flag);
    2871              : 
    2872              :   /* Similarly for alternate entry points.  */
    2873        43649 :   else if (alternate_entry
    2874           32 :            && (sym->ns->proc_name->backend_decl == current_function_decl
    2875            0 :                || parent_flag))
    2876              :     {
    2877           32 :       gfc_entry_list *el = NULL;
    2878              : 
    2879           51 :       for (el = sym->ns->entries; el; el = el->next)
    2880           51 :         if (sym == el->sym)
    2881              :           {
    2882           32 :             t = gfc_get_fake_result_decl (sym, parent_flag);
    2883           32 :             break;
    2884              :           }
    2885              :     }
    2886              : 
    2887        43617 :   else if (entry_master
    2888           12 :            && (sym->ns->proc_name->backend_decl == current_function_decl
    2889            0 :                || parent_flag))
    2890           12 :     t = gfc_get_fake_result_decl (sym, parent_flag);
    2891              : 
    2892              :   return t;
    2893              : }
    2894              : 
    2895              : static tree
    2896        11770 : gfc_trans_omp_variable_list (enum omp_clause_code code,
    2897              :                              gfc_omp_namelist *namelist, tree list,
    2898              :                              bool declare_simd)
    2899              : {
    2900              :   /* PARAMETER (named constants) are excluded as OpenACC 3.4 permits them now
    2901              :      as 'var' but permits compilers to ignore them.  In expressions, it should
    2902              :      have been replaced by the value (and this function should not be called
    2903              :      anyway) and for var-using clauses, they should just be skipped.  */
    2904        30374 :   for (; namelist != NULL; namelist = namelist->next)
    2905        18604 :     if ((namelist->sym->attr.referenced || declare_simd)
    2906        18604 :         && namelist->sym->attr.flavor != FL_PARAMETER)
    2907              :       {
    2908        18599 :         tree t = gfc_trans_omp_variable (namelist->sym, declare_simd);
    2909        18599 :         if (t != error_mark_node)
    2910              :           {
    2911        18599 :             tree node;
    2912        18599 :             node = build_omp_clause (input_location, code);
    2913        18599 :             OMP_CLAUSE_DECL (node) = t;
    2914        18599 :             list = gfc_trans_add_clause (node, list);
    2915              : 
    2916        18599 :             if (code == OMP_CLAUSE_LASTPRIVATE
    2917         2866 :                 && namelist->u.lastprivate_conditional)
    2918           88 :               OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (node) = 1;
    2919              :           }
    2920              :       }
    2921        11770 :   return list;
    2922              : }
    2923              : 
    2924              : struct omp_udr_find_orig_data
    2925              : {
    2926              :   gfc_omp_udr *omp_udr;
    2927              :   bool omp_orig_seen;
    2928              : };
    2929              : 
    2930              : static int
    2931          678 : omp_udr_find_orig (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
    2932              :                    void *data)
    2933              : {
    2934          678 :   struct omp_udr_find_orig_data *cd = (struct omp_udr_find_orig_data *) data;
    2935          678 :   if ((*e)->expr_type == EXPR_VARIABLE
    2936          366 :       && (*e)->symtree->n.sym == cd->omp_udr->omp_orig)
    2937           72 :     cd->omp_orig_seen = true;
    2938              : 
    2939          678 :   return 0;
    2940              : }
    2941              : 
    2942              : static void
    2943          686 : gfc_trans_omp_array_reduction_or_udr (tree c, gfc_omp_namelist *n, locus where)
    2944              : {
    2945          686 :   gfc_symbol *sym = n->sym;
    2946          686 :   gfc_symtree *root1 = NULL, *root2 = NULL, *root3 = NULL, *root4 = NULL;
    2947          686 :   gfc_symtree *symtree1, *symtree2, *symtree3, *symtree4 = NULL;
    2948          686 :   gfc_symbol init_val_sym, outer_sym, intrinsic_sym;
    2949          686 :   gfc_symbol omp_var_copy[4];
    2950          686 :   gfc_expr *e1, *e2, *e3, *e4;
    2951          686 :   gfc_ref *ref;
    2952          686 :   tree decl, backend_decl, stmt, type, outer_decl;
    2953          686 :   locus old_loc = gfc_current_locus;
    2954          686 :   const char *iname;
    2955          686 :   bool t;
    2956          686 :   gfc_omp_udr *udr = n->u2.udr ? n->u2.udr->udr : NULL;
    2957          686 :   gfc_namespace *old_ns = gfc_current_ns;
    2958              : 
    2959          686 :   if (gfc_current_ns->proc_name
    2960          686 :       && gfc_current_ns->proc_name->ns != gfc_current_ns)
    2961           41 :     gfc_current_ns = gfc_current_ns->proc_name->ns;
    2962              : 
    2963          686 :   decl = OMP_CLAUSE_DECL (c);
    2964          686 :   gfc_current_locus = where;
    2965          686 :   type = TREE_TYPE (decl);
    2966          686 :   outer_decl = create_tmp_var_raw (type);
    2967          686 :   if (TREE_CODE (decl) == PARM_DECL
    2968           31 :       && TREE_CODE (type) == REFERENCE_TYPE
    2969           12 :       && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (type))
    2970          698 :       && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (type)) == GFC_ARRAY_ALLOCATABLE)
    2971              :     {
    2972           12 :       decl = build_fold_indirect_ref (decl);
    2973           12 :       type = TREE_TYPE (type);
    2974              :     }
    2975              : 
    2976              :   /* Create a fake symbol for init value.  */
    2977          686 :   memset (&init_val_sym, 0, sizeof (init_val_sym));
    2978          686 :   init_val_sym.ns = sym->ns;
    2979          686 :   init_val_sym.name = sym->name;
    2980          686 :   init_val_sym.ts = sym->ts;
    2981          686 :   init_val_sym.attr.referenced = 1;
    2982          686 :   init_val_sym.declared_at = where;
    2983          686 :   init_val_sym.attr.flavor = FL_VARIABLE;
    2984          686 :   if (OMP_CLAUSE_REDUCTION_CODE (c) != ERROR_MARK)
    2985          284 :     backend_decl = omp_reduction_init (c, gfc_sym_type (&init_val_sym));
    2986          402 :   else if (udr->initializer_ns)
    2987              :     backend_decl = NULL;
    2988              :   else
    2989          132 :     switch (sym->ts.type)
    2990              :       {
    2991           15 :       case BT_LOGICAL:
    2992           15 :       case BT_INTEGER:
    2993           15 :       case BT_REAL:
    2994           15 :       case BT_COMPLEX:
    2995           15 :         backend_decl = build_zero_cst (gfc_sym_type (&init_val_sym));
    2996           15 :         break;
    2997              :       default:
    2998              :         backend_decl = NULL_TREE;
    2999              :         break;
    3000              :       }
    3001          686 :   init_val_sym.backend_decl = backend_decl;
    3002              : 
    3003              :   /* Create a fake symbol for the outer array reference.  */
    3004          686 :   outer_sym = *sym;
    3005          686 :   if (sym->as)
    3006          426 :     outer_sym.as = gfc_copy_array_spec (sym->as);
    3007          686 :   outer_sym.attr.dummy = 0;
    3008          686 :   outer_sym.attr.result = 0;
    3009          686 :   outer_sym.attr.flavor = FL_VARIABLE;
    3010          686 :   outer_sym.backend_decl = outer_decl;
    3011          686 :   if (decl != OMP_CLAUSE_DECL (c))
    3012           12 :     outer_sym.backend_decl = build_fold_indirect_ref (outer_decl);
    3013              : 
    3014              :   /* Create fake symtrees for it.  */
    3015          686 :   symtree1 = gfc_new_symtree (&root1, sym->name);
    3016          686 :   symtree1->n.sym = sym;
    3017          686 :   gcc_assert (symtree1 == root1);
    3018              : 
    3019          686 :   symtree2 = gfc_new_symtree (&root2, sym->name);
    3020          686 :   symtree2->n.sym = &init_val_sym;
    3021          686 :   gcc_assert (symtree2 == root2);
    3022              : 
    3023          686 :   symtree3 = gfc_new_symtree (&root3, sym->name);
    3024          686 :   symtree3->n.sym = &outer_sym;
    3025          686 :   gcc_assert (symtree3 == root3);
    3026              : 
    3027          686 :   memset (omp_var_copy, 0, sizeof omp_var_copy);
    3028          686 :   if (udr)
    3029              :     {
    3030          402 :       omp_var_copy[0] = *udr->omp_out;
    3031          402 :       omp_var_copy[1] = *udr->omp_in;
    3032          402 :       *udr->omp_out = outer_sym;
    3033          402 :       *udr->omp_in = *sym;
    3034          402 :       if (udr->initializer_ns)
    3035              :         {
    3036          270 :           omp_var_copy[2] = *udr->omp_priv;
    3037          270 :           omp_var_copy[3] = *udr->omp_orig;
    3038          270 :           *udr->omp_priv = *sym;
    3039          270 :           *udr->omp_orig = outer_sym;
    3040              :         }
    3041              :     }
    3042              : 
    3043              :   /* Create expressions.  */
    3044          686 :   e1 = gfc_get_expr ();
    3045          686 :   e1->expr_type = EXPR_VARIABLE;
    3046          686 :   e1->where = where;
    3047          686 :   e1->symtree = symtree1;
    3048          686 :   e1->ts = sym->ts;
    3049          686 :   if (sym->attr.dimension)
    3050              :     {
    3051          426 :       e1->ref = ref = gfc_get_ref ();
    3052          426 :       ref->type = REF_ARRAY;
    3053          426 :       ref->u.ar.where = where;
    3054          426 :       ref->u.ar.as = sym->as;
    3055          426 :       ref->u.ar.type = AR_FULL;
    3056          426 :       ref->u.ar.dimen = 0;
    3057              :     }
    3058          686 :   t = gfc_resolve_expr (e1);
    3059          686 :   gcc_assert (t);
    3060              : 
    3061          686 :   e2 = NULL;
    3062          686 :   if (backend_decl != NULL_TREE)
    3063              :     {
    3064          299 :       e2 = gfc_get_expr ();
    3065          299 :       e2->expr_type = EXPR_VARIABLE;
    3066          299 :       e2->where = where;
    3067          299 :       e2->symtree = symtree2;
    3068          299 :       e2->ts = sym->ts;
    3069          299 :       t = gfc_resolve_expr (e2);
    3070          299 :       gcc_assert (t);
    3071              :     }
    3072          387 :   else if (udr->initializer_ns == NULL)
    3073              :     {
    3074          117 :       gcc_assert (sym->ts.type == BT_DERIVED);
    3075          117 :       e2 = gfc_default_initializer (&sym->ts);
    3076          117 :       gcc_assert (e2);
    3077          117 :       t = gfc_resolve_expr (e2);
    3078          117 :       gcc_assert (t);
    3079              :     }
    3080          270 :   else if (n->u2.udr->initializer->op == EXEC_ASSIGN)
    3081              :     {
    3082          204 :       e2 = gfc_copy_expr (n->u2.udr->initializer->expr2);
    3083          204 :       t = gfc_resolve_expr (e2);
    3084          204 :       gcc_assert (t);
    3085              :     }
    3086          686 :   if (udr && udr->initializer_ns)
    3087              :     {
    3088          270 :       struct omp_udr_find_orig_data cd;
    3089          270 :       cd.omp_udr = udr;
    3090          270 :       cd.omp_orig_seen = false;
    3091          270 :       gfc_code_walker (&n->u2.udr->initializer,
    3092              :                        gfc_dummy_code_callback, omp_udr_find_orig, &cd);
    3093          270 :       if (cd.omp_orig_seen)
    3094           72 :         OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c) = 1;
    3095              :     }
    3096              : 
    3097          686 :   e3 = gfc_copy_expr (e1);
    3098          686 :   e3->symtree = symtree3;
    3099          686 :   t = gfc_resolve_expr (e3);
    3100          686 :   gcc_assert (t);
    3101              : 
    3102          686 :   iname = NULL;
    3103          686 :   e4 = NULL;
    3104          686 :   switch (OMP_CLAUSE_REDUCTION_CODE (c))
    3105              :     {
    3106          160 :     case PLUS_EXPR:
    3107          160 :     case MINUS_EXPR:
    3108          160 :       e4 = gfc_add (e3, e1);
    3109          160 :       break;
    3110           26 :     case MULT_EXPR:
    3111           26 :       e4 = gfc_multiply (e3, e1);
    3112           26 :       break;
    3113            6 :     case TRUTH_ANDIF_EXPR:
    3114            6 :       e4 = gfc_and (e3, e1);
    3115            6 :       break;
    3116            6 :     case TRUTH_ORIF_EXPR:
    3117            6 :       e4 = gfc_or (e3, e1);
    3118            6 :       break;
    3119            6 :     case EQ_EXPR:
    3120            6 :       e4 = gfc_eqv (e3, e1);
    3121            6 :       break;
    3122            6 :     case NE_EXPR:
    3123            6 :       e4 = gfc_neqv (e3, e1);
    3124            6 :       break;
    3125              :     case MIN_EXPR:
    3126              :       iname = "min";
    3127              :       break;
    3128              :     case MAX_EXPR:
    3129              :       iname = "max";
    3130              :       break;
    3131              :     case BIT_AND_EXPR:
    3132              :       iname = "iand";
    3133              :       break;
    3134              :     case BIT_IOR_EXPR:
    3135              :       iname = "ior";
    3136              :       break;
    3137              :     case BIT_XOR_EXPR:
    3138              :       iname = "ieor";
    3139              :       break;
    3140          402 :     case ERROR_MARK:
    3141          402 :       if (n->u2.udr->combiner->op == EXEC_ASSIGN)
    3142              :         {
    3143          336 :           gfc_free_expr (e3);
    3144          336 :           e3 = gfc_copy_expr (n->u2.udr->combiner->expr1);
    3145          336 :           e4 = gfc_copy_expr (n->u2.udr->combiner->expr2);
    3146          336 :           t = gfc_resolve_expr (e3);
    3147          336 :           gcc_assert (t);
    3148          336 :           t = gfc_resolve_expr (e4);
    3149          336 :           gcc_assert (t);
    3150              :         }
    3151              :       break;
    3152            0 :     default:
    3153            0 :       gcc_unreachable ();
    3154              :     }
    3155          210 :   if (iname != NULL)
    3156              :     {
    3157           74 :       memset (&intrinsic_sym, 0, sizeof (intrinsic_sym));
    3158           74 :       intrinsic_sym.ns = sym->ns;
    3159           74 :       intrinsic_sym.name = iname;
    3160           74 :       intrinsic_sym.ts = sym->ts;
    3161           74 :       intrinsic_sym.attr.referenced = 1;
    3162           74 :       intrinsic_sym.attr.intrinsic = 1;
    3163           74 :       intrinsic_sym.attr.function = 1;
    3164           74 :       intrinsic_sym.attr.implicit_type = 1;
    3165           74 :       intrinsic_sym.result = &intrinsic_sym;
    3166           74 :       intrinsic_sym.declared_at = where;
    3167              : 
    3168           74 :       symtree4 = gfc_new_symtree (&root4, iname);
    3169           74 :       symtree4->n.sym = &intrinsic_sym;
    3170           74 :       gcc_assert (symtree4 == root4);
    3171              : 
    3172           74 :       e4 = gfc_get_expr ();
    3173           74 :       e4->expr_type = EXPR_FUNCTION;
    3174           74 :       e4->where = where;
    3175           74 :       e4->symtree = symtree4;
    3176           74 :       e4->value.function.actual = gfc_get_actual_arglist ();
    3177           74 :       e4->value.function.actual->expr = e3;
    3178           74 :       e4->value.function.actual->next = gfc_get_actual_arglist ();
    3179           74 :       e4->value.function.actual->next->expr = e1;
    3180              :     }
    3181          686 :   if (OMP_CLAUSE_REDUCTION_CODE (c) != ERROR_MARK)
    3182              :     {
    3183              :       /* e1 and e3 have been stored as arguments of e4, avoid sharing.  */
    3184          284 :       e1 = gfc_copy_expr (e1);
    3185          284 :       e3 = gfc_copy_expr (e3);
    3186          284 :       t = gfc_resolve_expr (e4);
    3187          284 :       gcc_assert (t);
    3188              :     }
    3189              : 
    3190              :   /* Create the init statement list.  */
    3191          686 :   pushlevel ();
    3192          686 :   if (e2)
    3193          620 :     stmt = gfc_trans_assignment (e1, e2, false, false);
    3194              :   else
    3195           66 :     stmt = gfc_trans_call (n->u2.udr->initializer, false,
    3196              :                            NULL_TREE, NULL_TREE, false);
    3197          686 :   if (TREE_CODE (stmt) != BIND_EXPR)
    3198          197 :     stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
    3199              :   else
    3200          489 :     poplevel (0, 0);
    3201          686 :   OMP_CLAUSE_REDUCTION_INIT (c) = stmt;
    3202              : 
    3203              :   /* Create the merge statement list.  */
    3204          686 :   pushlevel ();
    3205          686 :   if (e4)
    3206          620 :     stmt = gfc_trans_assignment (e3, e4, false, true);
    3207              :   else
    3208           66 :     stmt = gfc_trans_call (n->u2.udr->combiner, false,
    3209              :                            NULL_TREE, NULL_TREE, false);
    3210          686 :   if (TREE_CODE (stmt) != BIND_EXPR)
    3211          236 :     stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
    3212              :   else
    3213          450 :     poplevel (0, 0);
    3214          686 :   OMP_CLAUSE_REDUCTION_MERGE (c) = stmt;
    3215              : 
    3216              :   /* And stick the placeholder VAR_DECL into the clause as well.  */
    3217          686 :   OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = outer_decl;
    3218              : 
    3219          686 :   gfc_current_locus = old_loc;
    3220              : 
    3221          686 :   gfc_free_expr (e1);
    3222          686 :   if (e2)
    3223          620 :     gfc_free_expr (e2);
    3224          686 :   gfc_free_expr (e3);
    3225          686 :   if (e4)
    3226          620 :     gfc_free_expr (e4);
    3227          686 :   free (symtree1);
    3228          686 :   free (symtree2);
    3229          686 :   free (symtree3);
    3230          686 :   free (symtree4);
    3231          686 :   if (outer_sym.as)
    3232          426 :     gfc_free_array_spec (outer_sym.as);
    3233              : 
    3234          686 :   if (udr)
    3235              :     {
    3236          402 :       *udr->omp_out = omp_var_copy[0];
    3237          402 :       *udr->omp_in = omp_var_copy[1];
    3238          402 :       if (udr->initializer_ns)
    3239              :         {
    3240          270 :           *udr->omp_priv = omp_var_copy[2];
    3241          270 :           *udr->omp_orig = omp_var_copy[3];
    3242              :         }
    3243              :     }
    3244              : 
    3245          686 :   gfc_current_ns = old_ns;
    3246          686 : }
    3247              : 
    3248              : static tree
    3249         3850 : gfc_trans_omp_reduction_list (int kind, gfc_omp_namelist *namelist, tree list,
    3250              :                               locus where, bool mark_addressable)
    3251              : {
    3252         3850 :   omp_clause_code clause = OMP_CLAUSE_REDUCTION;
    3253         3850 :   switch (kind)
    3254              :     {
    3255              :     case OMP_LIST_REDUCTION:
    3256              :     case OMP_LIST_REDUCTION_INSCAN:
    3257              :     case OMP_LIST_REDUCTION_TASK:
    3258              :       break;
    3259              :     case OMP_LIST_IN_REDUCTION:
    3260              :       clause = OMP_CLAUSE_IN_REDUCTION;
    3261              :       break;
    3262              :     case OMP_LIST_TASK_REDUCTION:
    3263              :       clause = OMP_CLAUSE_TASK_REDUCTION;
    3264              :       break;
    3265            0 :     default:
    3266            0 :       gcc_unreachable ();
    3267              :     }
    3268         8644 :   for (; namelist != NULL; namelist = namelist->next)
    3269         4794 :     if (namelist->sym->attr.referenced)
    3270              :       {
    3271         4794 :         tree t = gfc_trans_omp_variable (namelist->sym, false);
    3272         4794 :         if (t != error_mark_node)
    3273              :           {
    3274         4794 :             tree node = build_omp_clause (gfc_get_location (&namelist->where),
    3275              :                                           clause);
    3276         4794 :             OMP_CLAUSE_DECL (node) = t;
    3277         4794 :             if (mark_addressable)
    3278           38 :               TREE_ADDRESSABLE (t) = 1;
    3279         4794 :             if (kind == OMP_LIST_REDUCTION_INSCAN)
    3280           20 :               OMP_CLAUSE_REDUCTION_INSCAN (node) = 1;
    3281         4794 :             if (kind == OMP_LIST_REDUCTION_TASK)
    3282           92 :               OMP_CLAUSE_REDUCTION_TASK (node) = 1;
    3283         4794 :             switch (namelist->u.reduction_op)
    3284              :               {
    3285         2345 :               case OMP_REDUCTION_PLUS:
    3286         2345 :                 OMP_CLAUSE_REDUCTION_CODE (node) = PLUS_EXPR;
    3287         2345 :                 break;
    3288          198 :               case OMP_REDUCTION_MINUS:
    3289          198 :                 OMP_CLAUSE_REDUCTION_CODE (node) = MINUS_EXPR;
    3290          198 :                 break;
    3291          254 :               case OMP_REDUCTION_TIMES:
    3292          254 :                 OMP_CLAUSE_REDUCTION_CODE (node) = MULT_EXPR;
    3293          254 :                 break;
    3294           92 :               case OMP_REDUCTION_AND:
    3295           92 :                 OMP_CLAUSE_REDUCTION_CODE (node) = TRUTH_ANDIF_EXPR;
    3296           92 :                 break;
    3297          785 :               case OMP_REDUCTION_OR:
    3298          785 :                 OMP_CLAUSE_REDUCTION_CODE (node) = TRUTH_ORIF_EXPR;
    3299          785 :                 break;
    3300           86 :               case OMP_REDUCTION_EQV:
    3301           86 :                 OMP_CLAUSE_REDUCTION_CODE (node) = EQ_EXPR;
    3302           86 :                 break;
    3303           86 :               case OMP_REDUCTION_NEQV:
    3304           86 :                 OMP_CLAUSE_REDUCTION_CODE (node) = NE_EXPR;
    3305           86 :                 break;
    3306          218 :               case OMP_REDUCTION_MAX:
    3307          218 :                 OMP_CLAUSE_REDUCTION_CODE (node) = MAX_EXPR;
    3308          218 :                 break;
    3309          201 :               case OMP_REDUCTION_MIN:
    3310          201 :                 OMP_CLAUSE_REDUCTION_CODE (node) = MIN_EXPR;
    3311          201 :                 break;
    3312           40 :               case OMP_REDUCTION_IAND:
    3313           40 :                 OMP_CLAUSE_REDUCTION_CODE (node) = BIT_AND_EXPR;
    3314           40 :                 break;
    3315           49 :               case OMP_REDUCTION_IOR:
    3316           49 :                 OMP_CLAUSE_REDUCTION_CODE (node) = BIT_IOR_EXPR;
    3317           49 :                 break;
    3318           38 :               case OMP_REDUCTION_IEOR:
    3319           38 :                 OMP_CLAUSE_REDUCTION_CODE (node) = BIT_XOR_EXPR;
    3320           38 :                 break;
    3321          402 :               case OMP_REDUCTION_USER:
    3322          402 :                 OMP_CLAUSE_REDUCTION_CODE (node) = ERROR_MARK;
    3323          402 :                 break;
    3324            0 :               default:
    3325            0 :                 gcc_unreachable ();
    3326              :               }
    3327         4794 :             if (namelist->sym->attr.dimension
    3328         4368 :                 || namelist->u.reduction_op == OMP_REDUCTION_USER
    3329         4122 :                 || namelist->sym->attr.allocatable)
    3330          686 :               gfc_trans_omp_array_reduction_or_udr (node, namelist, where);
    3331         4794 :             list = gfc_trans_add_clause (node, list);
    3332              :           }
    3333              :       }
    3334         3850 :   return list;
    3335              : }
    3336              : 
    3337              : static inline tree
    3338         4957 : gfc_convert_expr_to_tree (stmtblock_t *block, gfc_expr *expr)
    3339              : {
    3340         4957 :   gfc_se se;
    3341         4957 :   tree result;
    3342              : 
    3343         4957 :   gfc_init_se (&se, NULL );
    3344         4957 :   gfc_conv_expr (&se, expr);
    3345         4957 :   gfc_add_block_to_block (block, &se.pre);
    3346         4957 :   result = gfc_evaluate_now (se.expr, block);
    3347         4957 :   gfc_add_block_to_block (block, &se.post);
    3348              : 
    3349         4957 :   return result;
    3350              : }
    3351              : 
    3352              : static vec<tree, va_heap, vl_embed> *doacross_steps;
    3353              : 
    3354              : 
    3355              : /* Map an array section or array element.
    3356              :    BLOCK will hold any output statements generated; if there are iterators,
    3357              :      it's a block for the current iterator group.
    3358              :    OP is the construct containing the map clause.
    3359              :    N is the entry that appears in the clause namelist.  It may contain iterator
    3360              :      variables.
    3361              :    DECL is the base object associated with the namelist entry.  It can be an
    3362              :      array descriptor, a bare array, or pointer to an array.
    3363              :    ELEMENT is true for an array element, false for an array section.
    3364              :    OPENMP is true for OpenMP, false for OpenACC.
    3365              :    PTR_KIND is the map operation.
    3366              :    NODE is an input operand representing the map clause.
    3367              :    NODE2, NODE3, and NODE4 are output operands that will hold new map clauses
    3368              :      generated by this function.  Not all of them are always needed.  NODE2
    3369              :      is for an array descriptor object, NODE3 is for its data array, NODE4
    3370              :      is for a pointer mapping.
    3371              :    ITERATOR is a list of active iterator descriptors, chained through
    3372              :      TREE_CHAIN.  */
    3373              : 
    3374              : static void
    3375         4116 : gfc_trans_omp_array_section (stmtblock_t *block, gfc_exec_op op,
    3376              :                              gfc_omp_namelist *n, tree decl, bool element,
    3377              :                              bool openmp, gomp_map_kind ptr_kind, tree &node,
    3378              :                              tree &node2, tree &node3, tree &node4,
    3379              :                              tree iterator)
    3380              : {
    3381         4116 :   gfc_se se;
    3382              :   /* PTR is the array expression from n->expr.  If iterators are this
    3383              :      involved expression can involve iterator variables.  BASE points to the
    3384              :      base array object obtained from DECL.  */
    3385         4116 :   tree ptr, base;
    3386         4116 :   tree elemsz = NULL_TREE;
    3387              : 
    3388         4116 :   gfc_init_se (&se, NULL);
    3389         4116 :   if (element)
    3390              :     {
    3391          185 :       gfc_conv_expr_reference (&se, n->expr);
    3392          185 :       gfc_add_block_to_block (block, &se.pre);
    3393          185 :       ptr = se.expr;
    3394              :     }
    3395              :   else
    3396              :     {
    3397         3931 :       gfc_conv_expr_descriptor (&se, n->expr);
    3398         3931 :       ptr = gfc_conv_array_data (se.expr);
    3399              :     }
    3400         4116 :   if (n->expr->ts.type == BT_CHARACTER && n->expr->ts.deferred)
    3401              :     {
    3402            0 :       gcc_assert (se.string_length);
    3403            0 :       tree len = gfc_evaluate_now (se.string_length, block);
    3404            0 :       elemsz = gfc_get_char_type (n->expr->ts.kind);
    3405            0 :       elemsz = TYPE_SIZE_UNIT (elemsz);
    3406            0 :       elemsz = fold_build2 (MULT_EXPR, size_type_node,
    3407              :                             fold_convert (size_type_node, len), elemsz);
    3408              :     }
    3409         4116 :   if (element)
    3410              :     {
    3411          185 :       if (!elemsz)
    3412          185 :         elemsz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ptr)));
    3413          185 :       OMP_CLAUSE_SIZE (node) = elemsz;
    3414              :     }
    3415              :   else
    3416              :     {
    3417         3931 :       tree type = TREE_TYPE (se.expr);
    3418         3931 :       gfc_add_block_to_block (block, &se.pre);
    3419         3931 :       OMP_CLAUSE_SIZE (node) = gfc_full_array_size (block, se.expr,
    3420         3931 :                                                     GFC_TYPE_ARRAY_RANK (type));
    3421         3931 :       if (!elemsz)
    3422         3931 :         elemsz = TYPE_SIZE_UNIT (gfc_get_element_type (type));
    3423         3931 :       elemsz = fold_convert (gfc_array_index_type, elemsz);
    3424         3931 :       OMP_CLAUSE_SIZE (node) = fold_build2 (MULT_EXPR, gfc_array_index_type,
    3425              :                                             OMP_CLAUSE_SIZE (node), elemsz);
    3426         3931 :       if (n->expr->ts.type == BT_DERIVED
    3427           21 :           && n->expr->ts.u.derived->attr.alloc_comp)
    3428              :         {
    3429              :           /* Save array descriptor for use in gfc_omp_deep_mapping{,_p,_cnt};
    3430              :              force evaluate to ensure that it is not gimplified + is a decl.  */
    3431           15 :           tree tmp = OMP_CLAUSE_SIZE (node);
    3432           15 :           tree var = gfc_create_var (TREE_TYPE (tmp), NULL);
    3433           15 :           gfc_add_modify_loc (input_location, block, var, tmp);
    3434           15 :           OMP_CLAUSE_SIZE (node) = var;
    3435           15 :           gfc_allocate_lang_decl (var);
    3436           15 :           GFC_DECL_SAVED_DESCRIPTOR (var) = se.expr;
    3437              :         }
    3438              :     }
    3439         4116 :   gcc_assert (se.post.head == NULL_TREE);
    3440         4116 :   gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
    3441         4116 :   OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr);
    3442         4116 :   ptr = fold_convert (ptrdiff_type_node, ptr);
    3443              : 
    3444         7946 :   if (POINTER_TYPE_P (TREE_TYPE (decl))
    3445          365 :       && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (decl)))
    3446           79 :       && ptr_kind == GOMP_MAP_POINTER
    3447           79 :       && op != EXEC_OMP_TARGET_EXIT_DATA
    3448           79 :       && OMP_CLAUSE_MAP_KIND (node) != GOMP_MAP_RELEASE
    3449         4195 :       && OMP_CLAUSE_MAP_KIND (node) != GOMP_MAP_DELETE)
    3450              : 
    3451              :     {
    3452              :       /* NODE4 is a newly-generated map clause for the pointer.  */
    3453           79 :       node4 = build_omp_clause (input_location,
    3454              :                                 OMP_CLAUSE_MAP);
    3455           79 :       OMP_CLAUSE_SET_MAP_KIND (node4, GOMP_MAP_POINTER);
    3456           79 :       OMP_CLAUSE_DECL (node4) = decl;
    3457           79 :       OMP_CLAUSE_SIZE (node4) = size_int (0);
    3458              :       /* Make DECL be the descriptor rather than the pointer to it.  */
    3459           79 :       decl = build_fold_indirect_ref (decl);
    3460              :     }
    3461         4037 :   else if (ptr_kind == GOMP_MAP_ALWAYS_POINTER
    3462            0 :            && n->expr->ts.type == BT_CHARACTER
    3463            0 :            && n->expr->ts.deferred)
    3464              :     {
    3465            0 :       gomp_map_kind map_kind;
    3466            0 :       if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_DELETE)
    3467            0 :         map_kind = OMP_CLAUSE_MAP_KIND (node);
    3468            0 :       else if (op == EXEC_OMP_TARGET_EXIT_DATA
    3469            0 :                || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_RELEASE)
    3470              :         map_kind = GOMP_MAP_RELEASE;
    3471              :       else
    3472              :         map_kind = GOMP_MAP_TO;
    3473            0 :       gcc_assert (se.string_length);
    3474            0 :       node4 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
    3475            0 :       OMP_CLAUSE_SET_MAP_KIND (node4, map_kind);
    3476            0 :       OMP_CLAUSE_DECL (node4) = se.string_length;
    3477            0 :       OMP_CLAUSE_SIZE (node4) = TYPE_SIZE_UNIT (gfc_charlen_type_node);
    3478              :     }
    3479         4116 :   if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
    3480              :     {
    3481         2779 :       tree type = TREE_TYPE (decl);
    3482         2779 :       base = gfc_conv_descriptor_data_get (decl);
    3483              :       /* NODE2 is a newly-generated map clause for the array descriptor DECL.  */
    3484         2779 :       node2 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
    3485         2779 :       OMP_CLAUSE_DECL (node2) = decl;
    3486         2779 :       OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type);
    3487         2779 :       if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_DELETE
    3488         2778 :           || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_RELEASE
    3489         2569 :           || op == EXEC_OMP_TARGET_EXIT_DATA
    3490         5348 :           || op == EXEC_OACC_EXIT_DATA)
    3491              :         {
    3492          392 :           gomp_map_kind map_kind
    3493          392 :             = OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_DELETE ? GOMP_MAP_DELETE
    3494          391 :                                                             : GOMP_MAP_RELEASE;
    3495          392 :           OMP_CLAUSE_SET_MAP_KIND (node2, map_kind);
    3496          392 :           OMP_CLAUSE_RELEASE_DESCRIPTOR (node2) = 1;
    3497              :         }
    3498              :       else
    3499         2387 :         OMP_CLAUSE_SET_MAP_KIND (node2, GOMP_MAP_TO_PSET);
    3500              :       /* NODE3 is a newly-generated map clause for the array data.  */
    3501         2779 :       node3 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
    3502         2779 :       OMP_CLAUSE_SET_MAP_KIND (node3, ptr_kind);
    3503         2779 :       OMP_CLAUSE_DECL (node3) = gfc_conv_descriptor_data_get (decl);
    3504              :       /* This purposely does not include GOMP_MAP_ALWAYS_POINTER.  The extra
    3505              :          cast prevents gimplify.cc from recognising it as being part of the
    3506              :          struct - and adding an 'alloc: for the 'desc.data' pointer, which
    3507              :          would break as the 'desc' (the descriptor) is also mapped
    3508              :          (see node4 above).  */
    3509         2779 :       if (ptr_kind == GOMP_MAP_ATTACH_DETACH && !openmp)
    3510          141 :         STRIP_NOPS (OMP_CLAUSE_DECL (node3));
    3511              :     }
    3512              :   else  /* DECL is bare array or pointer to an array.  */
    3513              :     {
    3514         1337 :       if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
    3515              :         {
    3516         1051 :           tree offset;
    3517         1051 :           base = build_fold_addr_expr (decl);
    3518         1051 :           offset = fold_build2 (MINUS_EXPR, ptrdiff_type_node, ptr,
    3519              :                                 fold_convert (ptrdiff_type_node, base));
    3520         1051 :           offset = build2 (TRUNC_DIV_EXPR, ptrdiff_type_node,
    3521              :                            offset, fold_convert (ptrdiff_type_node, elemsz));
    3522         1051 :           offset = build4_loc (input_location, ARRAY_REF,
    3523         1051 :                                TREE_TYPE (TREE_TYPE (decl)),
    3524              :                                decl, offset, NULL_TREE, NULL_TREE);
    3525         1051 :           OMP_CLAUSE_DECL (node) = offset;
    3526              : 
    3527         1051 :           if (ptr_kind == GOMP_MAP_ATTACH_DETACH && openmp)
    3528          145 :             return;
    3529              :         }
    3530              :       else  /* DECL is a pointer.  */
    3531              :         {
    3532          286 :           gcc_assert (POINTER_TYPE_P (TREE_TYPE (decl)));
    3533              :           base = decl;
    3534              :         }
    3535         1192 :       node3 = build_omp_clause (input_location,
    3536              :                                 OMP_CLAUSE_MAP);
    3537         1192 :       OMP_CLAUSE_SET_MAP_KIND (node3, ptr_kind);
    3538         1192 :       OMP_CLAUSE_DECL (node3) = decl;
    3539              :     }
    3540              : 
    3541              :   /* FIXME: This is a broken hack.  The ptr expression is based on the
    3542              :      namelist entry and can contain references to iterator variables, which
    3543              :      are not yet set to their initial values when ptr is used.  This
    3544              :      tries to replace instances of the iterator values with the initial values
    3545              :      in ptr explicitly.  It's broken because the expansion of ptr can also
    3546              :      add statements to the iterator block that also contain references to
    3547              :      the uninitialized variables, and substituting those similarly breaks
    3548              :      other things.  */
    3549         3971 :   base = fold_convert (ptrdiff_type_node, base);
    3550         4022 :   for (tree it = iterator; it; it = TREE_CHAIN (it))
    3551              :     {
    3552           51 :       ptr = simplify_replace_tree (ptr, OMP_ITERATOR_VAR (it),
    3553           51 :                                    OMP_ITERATOR_BEGIN (it));
    3554           51 :       base = simplify_replace_tree (base, OMP_ITERATOR_VAR (it),
    3555           51 :                                     OMP_ITERATOR_BEGIN (it));
    3556              :     }
    3557              : 
    3558              :   /* The OMP_CLAUSE_SIZE field for the array data map clause node3
    3559              :      contains the initial offset of ptr from base, not the size.  */
    3560         3971 :   OMP_CLAUSE_SIZE (node3) = fold_build2 (MINUS_EXPR, ptrdiff_type_node,
    3561              :                                          ptr, base);
    3562              : }
    3563              : 
    3564              : /* Construct a list of omp_iterator objects for the iterators specified
    3565              :    in NS.  Initialization statements for the start/end/step expressions
    3566              :    are added to OUTER_BLOCK.  BLOCK is the tree block that contains the
    3567              :    iterator variable bindings.  */
    3568              : static tree
    3569           94 : handle_iterator (gfc_namespace *ns, stmtblock_t *outer_block, tree block)
    3570              : {
    3571           94 :   tree list = NULL_TREE;
    3572          203 :   for (gfc_symbol *sym = ns->omp_affinity_iterators; sym; sym = sym->tlink)
    3573              :     {
    3574          109 :       gfc_constructor *c;
    3575          109 :       gfc_se se;
    3576              : 
    3577          109 :       tree last = make_omp_iterator ();
    3578          109 :       tree iter_var = gfc_get_symbol_decl (sym);
    3579          109 :       tree type = TREE_TYPE (iter_var);
    3580          109 :       OMP_ITERATOR_VAR (last) = iter_var;
    3581          109 :       DECL_CHAIN (iter_var) = BLOCK_VARS (block);
    3582          109 :       BLOCK_VARS (block) = iter_var;
    3583              : 
    3584              :       /* begin */
    3585          109 :       c = gfc_constructor_first (sym->value->value.constructor);
    3586          109 :       gfc_init_se (&se, NULL);
    3587          109 :       gfc_conv_expr (&se, c->expr);
    3588          109 :       gfc_add_block_to_block (outer_block, &se.pre);
    3589          109 :       gfc_add_block_to_block (outer_block, &se.post);
    3590          109 :       OMP_ITERATOR_BEGIN (last) = fold_convert (type,
    3591              :                                                 gfc_evaluate_now (se.expr,
    3592              :                                                                   outer_block));
    3593              :       /* end */
    3594          109 :       c = gfc_constructor_next (c);
    3595          109 :       gfc_init_se (&se, NULL);
    3596          109 :       gfc_conv_expr (&se, c->expr);
    3597          109 :       gfc_add_block_to_block (outer_block, &se.pre);
    3598          109 :       gfc_add_block_to_block (outer_block, &se.post);
    3599          109 :       OMP_ITERATOR_END (last) = fold_convert (type,
    3600              :                                               gfc_evaluate_now (se.expr,
    3601              :                                                                 outer_block));
    3602              :       /* step */
    3603          109 :       c = gfc_constructor_next (c);
    3604          109 :       tree step;
    3605          109 :       if (c)
    3606              :         {
    3607            5 :           gfc_init_se (&se, NULL);
    3608            5 :           gfc_conv_expr (&se, c->expr);
    3609            5 :           gfc_add_block_to_block (outer_block, &se.pre);
    3610            5 :           gfc_add_block_to_block (outer_block, &se.post);
    3611            5 :           gfc_conv_expr (&se, c->expr);
    3612            5 :           step = fold_convert (type,
    3613              :                                gfc_evaluate_now (se.expr,
    3614              :                                                  outer_block));
    3615              :         }
    3616              :       else
    3617          104 :         step = build_int_cst (type, 1);
    3618          109 :       OMP_ITERATOR_STEP (last) = step;
    3619              :       /* orig_step */
    3620          109 :       OMP_ITERATOR_ORIG_STEP (last) = save_expr (step);
    3621          109 :       TREE_CHAIN (last) = list;
    3622          109 :       list = last;
    3623              :     }
    3624           94 :   return list;
    3625              : }
    3626              : 
    3627              : /* Start an iterator group for the iterators in NS.  OUTER_BLOCK is the
    3628              :    statement block to hold side-effects from evaluating the iterator
    3629              :    start/end/step expressions, and ITER_BLOCK is set to a newly initialized
    3630              :    block for the scope of the iterators.  TREE_BLOCK is set to a new
    3631              :    tree BLOCK node to hold the iterator variables.  Returns the list of
    3632              :    omp_iterator objects, as per handle_iterator above.  */
    3633              : static tree
    3634           94 : start_iterator_group (gfc_namespace *ns, stmtblock_t *outer_block,
    3635              :                       stmtblock_t *iter_block, tree &tree_block)
    3636              : {
    3637           94 :   gfc_init_block (iter_block);
    3638           94 :   tree_block = make_node (BLOCK);
    3639           94 :   TREE_USED (tree_block) = 1;
    3640           94 :   BLOCK_VARS (tree_block) = NULL_TREE;
    3641           94 :   return handle_iterator (ns, outer_block, tree_block);
    3642              : }
    3643              : 
    3644              : /* Finish an iterator group.  LIST identifies the namelist type for the
    3645              :    clause.  ITER_BLOCK is the statement block within the scope of the
    3646              :    iterators, and TREE_BLOCK is the block for the iterator variables.
    3647              :    ITERATOR is the list of omp_iterator objects as previously returned by
    3648              :    start_iterator_group.  OMP_CLAUSES is the list of clauses the iterators
    3649              :    apply to, ending at PREV_CLAUSES.  */
    3650              : static void
    3651           94 : finish_iterator_group (int list, stmtblock_t *iter_block, tree tree_block,
    3652              :                        tree iterator, tree omp_clauses, tree prev_clauses)
    3653              : {
    3654           94 :   gcc_assert (iterator);
    3655           94 :   BLOCK_SUBBLOCKS (tree_block) = gfc_finish_block (iter_block);
    3656           94 :   OMP_ITERATOR_BLOCK (iterator) = tree_block;
    3657          276 :   for (tree c = omp_clauses; c != prev_clauses; c = OMP_CLAUSE_CHAIN (c))
    3658          182 :     switch (list)
    3659              :       {
    3660           56 :       case OMP_LIST_AFFINITY:
    3661           56 :       case OMP_LIST_DEPEND:
    3662           56 :         OMP_CLAUSE_DECL (c) = build_tree_list (iterator, OMP_CLAUSE_DECL (c));
    3663           56 :         break;
    3664          112 :       case OMP_LIST_MAP:
    3665          112 :         if (OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
    3666          112 :             && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_REFERENCE)
    3667          108 :           OMP_CLAUSE_ITERATORS (c) = iterator;
    3668              :         break;
    3669           14 :       case OMP_LIST_TO:
    3670           14 :       case OMP_LIST_FROM:
    3671           14 :       case OMP_LIST_CACHE:
    3672           14 :         OMP_CLAUSE_ITERATORS (c) = iterator;
    3673           14 :         break;
    3674            0 :       default:
    3675            0 :         gcc_unreachable ();
    3676              :       }
    3677           94 : }
    3678              : 
    3679              : /* To alleviate quadratic behaviour in checking each entry of a
    3680              :    gfc_omp_namelist against every other entry, we build a hashtable indexed by
    3681              :    gfc_symbol pointer, which we can use in the usual case that a map
    3682              :    expression has a symbol as its root term.  Return a namelist based on the
    3683              :    root symbol used by N, building a new table in SYM_ROOTED_NL using the
    3684              :    gfc_omp_namelist N2 (all clauses) if we haven't done so already.  */
    3685              : 
    3686              : static gfc_omp_namelist *
    3687          934 : get_symbol_rooted_namelist (hash_map<gfc_symbol *,
    3688              :                                      gfc_omp_namelist *> *&sym_rooted_nl,
    3689              :                             gfc_omp_namelist *n,
    3690              :                             gfc_omp_namelist *n2, bool *sym_based)
    3691              : {
    3692              :   /* Early-out if we have a NULL clause list (e.g. for OpenACC).  */
    3693          934 :   if (!n2)
    3694              :     return NULL;
    3695              : 
    3696          897 :   gfc_symbol *use_sym = NULL;
    3697              : 
    3698              :   /* We're only interested in cases where we have an expression, e.g. a
    3699              :      component access.  */
    3700          897 :   if (n->expr && n->expr->expr_type == EXPR_VARIABLE && n->expr->symtree)
    3701          897 :     use_sym = n->expr->symtree->n.sym;
    3702              : 
    3703          897 :   *sym_based = false;
    3704              : 
    3705          897 :   if (!use_sym)
    3706              :     return n2;
    3707              : 
    3708          897 :   if (!sym_rooted_nl)
    3709              :     {
    3710          388 :       sym_rooted_nl = new hash_map<gfc_symbol *, gfc_omp_namelist *> ();
    3711              : 
    3712         1715 :       for (; n2 != NULL; n2 = n2->next)
    3713              :         {
    3714         1327 :           if (!n2->expr
    3715         1326 :               || n2->expr->expr_type != EXPR_VARIABLE
    3716         1326 :               || !n2->expr->symtree)
    3717            1 :             continue;
    3718              : 
    3719         1326 :           gfc_omp_namelist *nl_copy = gfc_get_omp_namelist ();
    3720         1326 :           memcpy (nl_copy, n2, sizeof *nl_copy);
    3721         1326 :           nl_copy->u2.duplicate_of = n2;
    3722         1326 :           nl_copy->next = NULL;
    3723              : 
    3724         1326 :           gfc_symbol *idx_sym = n2->expr->symtree->n.sym;
    3725              : 
    3726         1326 :           bool existed;
    3727         1326 :           gfc_omp_namelist *&entry
    3728         1326 :             = sym_rooted_nl->get_or_insert (idx_sym, &existed);
    3729         1326 :           if (existed)
    3730          881 :             nl_copy->next = entry;
    3731         1326 :           entry = nl_copy;
    3732              :         }
    3733              :     }
    3734              : 
    3735          897 :   gfc_omp_namelist **n2_sym = sym_rooted_nl->get (use_sym);
    3736              : 
    3737          897 :   if (n2_sym)
    3738              :     {
    3739          897 :       *sym_based = true;
    3740          897 :       return *n2_sym;
    3741              :     }
    3742              : 
    3743              :   return NULL;
    3744              : }
    3745              : 
    3746              : /* Helper function for gfc_trans_omp_clauses.  Adjust existing and create new
    3747              :    map nodes for derived-type component array descriptors. Return true if the
    3748              :    mapping has to be dropped.  */
    3749              : 
    3750              : static bool
    3751         1191 : gfc_map_array_descriptor (
    3752              :   tree &node, tree &node2, tree &node3, tree &node4, tree descr, bool openacc,
    3753              :   location_t map_loc, stmtblock_t *block, gfc_exec_op op, gfc_omp_namelist *n,
    3754              :   hash_map<gfc_symbol *, gfc_omp_namelist *> *&sym_rooted_nl, gfc_se se,
    3755              :   gfc_omp_clauses *clauses, bool mid_desc_p)
    3756              : {
    3757         1191 :   tree type = TREE_TYPE (descr);
    3758         1191 :   tree ptr = gfc_conv_descriptor_data_get (descr);
    3759         1191 :   ptr = build_fold_indirect_ref (ptr);
    3760         1191 :   OMP_CLAUSE_DECL (node) = ptr;
    3761         1191 :   int rank = GFC_TYPE_ARRAY_RANK (type);
    3762         1191 :   OMP_CLAUSE_SIZE (node) = gfc_full_array_size (block, descr, rank);
    3763         1191 :   tree elemsz = TYPE_SIZE_UNIT (gfc_get_element_type (type));
    3764              : 
    3765         1191 :   gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (node);
    3766         1191 :   if (GOMP_MAP_COPY_TO_P (map_kind) || map_kind == GOMP_MAP_ALLOC)
    3767              :     {
    3768          842 :       if (mid_desc_p)
    3769              :         {
    3770              :           /* For an intermediate descriptor, the pointee (i.e. the actual array
    3771              :              content) is mapped in a separate set of nodes. This ALLOC is only
    3772              :              emitted to comply with the group layout expected by the gimplifier.
    3773              :             */
    3774           89 :           OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALLOC);
    3775           89 :           OMP_CLAUSE_SIZE (node) = size_zero_node;
    3776           89 :           OMP_CLAUSE_MAP_GIMPLE_ONLY (node) = 1;
    3777              :         }
    3778              :       else
    3779          753 :         map_kind
    3780         1250 :           = ((GOMP_MAP_ALWAYS_P (map_kind) || gfc_expr_attr (n->expr).pointer)
    3781          753 :                ? GOMP_MAP_ALWAYS_TO
    3782              :                : GOMP_MAP_TO);
    3783              :     }
    3784          349 :   else if (n->u.map.op == OMP_MAP_RELEASE || n->u.map.op == OMP_MAP_DELETE)
    3785              :     ;
    3786          344 :   else if (op == EXEC_OMP_TARGET_EXIT_DATA || op == EXEC_OACC_EXIT_DATA)
    3787              :     map_kind = GOMP_MAP_RELEASE;
    3788           31 :   else if (mid_desc_p)
    3789              :     {
    3790              :       /* For an intermediate descriptor, the pointee (i.e. the actual array
    3791              :          content) is mapped in a separate set of nodes. This ALLOC is only
    3792              :          emitted to comply with the group layout expected by the gimplifier.  */
    3793            1 :       OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALLOC);
    3794            1 :       OMP_CLAUSE_SIZE (node) = size_zero_node;
    3795            1 :       OMP_CLAUSE_MAP_GIMPLE_ONLY (node) = 1;
    3796              :     }
    3797              :   else
    3798              :     map_kind = GOMP_MAP_ALLOC;
    3799              : 
    3800         1191 :   if (!openacc && n->expr->ts.type == BT_CHARACTER && n->expr->ts.deferred)
    3801              :     {
    3802           42 :       gcc_assert (se.string_length);
    3803           42 :       tree len = fold_convert (size_type_node, se.string_length);
    3804           42 :       elemsz = gfc_get_char_type (n->expr->ts.kind);
    3805           42 :       elemsz = TYPE_SIZE_UNIT (elemsz);
    3806           42 :       elemsz = fold_build2 (MULT_EXPR, size_type_node, len, elemsz);
    3807           42 :       node4 = build_omp_clause (map_loc, OMP_CLAUSE_MAP);
    3808           42 :       OMP_CLAUSE_SET_MAP_KIND (node4, map_kind);
    3809           42 :       OMP_CLAUSE_DECL (node4) = se.string_length;
    3810           42 :       OMP_CLAUSE_SIZE (node4) = TYPE_SIZE_UNIT (gfc_charlen_type_node);
    3811              :     }
    3812         1191 :   elemsz = fold_convert (gfc_array_index_type, elemsz);
    3813         1191 :   OMP_CLAUSE_SIZE (node) = fold_build2 (MULT_EXPR, gfc_array_index_type,
    3814              :                                         OMP_CLAUSE_SIZE (node), elemsz);
    3815              : 
    3816         1191 :   node2 = build_omp_clause (map_loc, OMP_CLAUSE_MAP);
    3817         1191 :   if (map_kind == GOMP_MAP_RELEASE || map_kind == GOMP_MAP_DELETE)
    3818              :     {
    3819          318 :       OMP_CLAUSE_SET_MAP_KIND (node2, map_kind);
    3820          318 :       OMP_CLAUSE_RELEASE_DESCRIPTOR (node2) = 1;
    3821              :     }
    3822              :   else
    3823          873 :     OMP_CLAUSE_SET_MAP_KIND (node2, GOMP_MAP_TO_PSET);
    3824         1191 :   OMP_CLAUSE_DECL (node2) = descr;
    3825         1191 :   OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type);
    3826              : 
    3827         1191 :   if (!openacc)
    3828              :     {
    3829         1051 :       if (n->expr->ts.type == BT_DERIVED
    3830           18 :           && n->expr->ts.u.derived->attr.alloc_comp)
    3831              :         {
    3832              :           /* Save array descriptor for use
    3833              :              in gfc_omp_deep_mapping{,_p,_cnt}; force
    3834              :              evaluate to ensure that it is
    3835              :              not gimplified + is a decl.  */
    3836           12 :           tree tmp = OMP_CLAUSE_SIZE (node);
    3837           12 :           tree var = gfc_create_var (TREE_TYPE (tmp), NULL);
    3838           12 :           gfc_add_modify_loc (map_loc, block, var, tmp);
    3839           12 :           OMP_CLAUSE_SIZE (node) = var;
    3840           12 :           gfc_allocate_lang_decl (var);
    3841           12 :           GFC_DECL_SAVED_DESCRIPTOR (var) = descr;
    3842              :         }
    3843              : 
    3844              :       /* If we don't have a mapping of a smaller part
    3845              :           of the array -- or we can't prove that we do
    3846              :           statically -- set this flag.  If there is a
    3847              :           mapping of a smaller part of the array after
    3848              :           all, this will turn into a no-op at
    3849              :           runtime.  */
    3850         1051 :       OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (node) = 1;
    3851              : 
    3852         1051 :       bool drop_mapping = false;
    3853              : 
    3854         1051 :       if (!mid_desc_p)
    3855              :         {
    3856          879 :           gfc_omp_namelist *n2 = clauses->lists[OMP_LIST_MAP];
    3857              : 
    3858          879 :           bool sym_based;
    3859          879 :           n2 = get_symbol_rooted_namelist (sym_rooted_nl, n, n2, &sym_based);
    3860              : 
    3861         3179 :           for (; n2 != NULL; n2 = n2->next)
    3862              :             {
    3863         2586 :               if ((!sym_based && n == n2)
    3864         2586 :                   || (sym_based && n == n2->u2.duplicate_of) || !n2->expr)
    3865          617 :                 continue;
    3866              : 
    3867         1969 :               if (!gfc_omp_expr_prefix_same (n->expr, n2->expr))
    3868         1683 :                 continue;
    3869              : 
    3870          286 :               gfc_ref *ref1 = n->expr->ref;
    3871          286 :               gfc_ref *ref2 = n2->expr->ref;
    3872              : 
    3873              :               /* We know ref1 and ref2 overlap.  We're
    3874              :                  interested in whether ref2 describes a
    3875              :                  smaller part of the array than ref1, which
    3876              :                  we already know refers to the full
    3877              :                  array.  */
    3878              : 
    3879          644 :               while (ref1->next && ref2->next)
    3880              :                 {
    3881              :                   ref1 = ref1->next;
    3882              :                   ref2 = ref2->next;
    3883              :                 }
    3884              : 
    3885          286 :               if (ref2->next
    3886          286 :                   || (ref2->type == REF_ARRAY
    3887          286 :                       && (ref2->u.ar.type == AR_ELEMENT
    3888          286 :                           || (ref2->u.ar.type == AR_SECTION))))
    3889              :                 {
    3890              :                   drop_mapping = true;
    3891              :                   break;
    3892              :                 }
    3893              :             }
    3894          879 :           if (drop_mapping)
    3895          286 :             return true;
    3896              :         }
    3897              :     }
    3898              : 
    3899          905 :   if (mid_desc_p && GOMP_MAP_COPY_FROM_P (OMP_CLAUSE_MAP_KIND (node)))
    3900           82 :     node = NULL_TREE;
    3901              : 
    3902          905 :   node3 = build_omp_clause (map_loc, OMP_CLAUSE_MAP);
    3903          905 :   OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_ATTACH_DETACH);
    3904          905 :   OMP_CLAUSE_DECL (node3) = gfc_conv_descriptor_data_get (descr);
    3905              :   /* Similar to gfc_trans_omp_array_section (details
    3906              :      there), we add/keep the cast for OpenMP to prevent
    3907              :      that an 'alloc:' gets added for node3 ('desc.data')
    3908              :      as that is part of the whole descriptor (node3).
    3909              :      TODO: Remove once the ME handles this properly.  */
    3910          905 :   if (!openacc)
    3911          765 :     OMP_CLAUSE_DECL (node3) = fold_convert (TREE_TYPE (TREE_OPERAND (ptr, 0)),
    3912              :                                             OMP_CLAUSE_DECL (node3));
    3913              :   else
    3914          140 :     STRIP_NOPS (OMP_CLAUSE_DECL (node3));
    3915          905 :   OMP_CLAUSE_SIZE (node3) = size_zero_node;
    3916          905 :   if (mid_desc_p)
    3917          172 :     OMP_CLAUSE_MAP_SIZE_NEEDS_ADJUSTMENT (node3) = 1;
    3918              : 
    3919              :   return false;
    3920              : }
    3921              : 
    3922              : static tree
    3923        32232 : gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
    3924              :                        locus where, bool declare_simd = false,
    3925              :                        bool openacc = false, gfc_exec_op op = EXEC_NOP)
    3926              : {
    3927        32232 :   tree omp_clauses = NULL_TREE, prev_clauses, chunk_size, c;
    3928        32232 :   tree iterator = NULL_TREE;
    3929        32232 :   tree tree_block = NULL_TREE;
    3930        32232 :   stmtblock_t iter_block;
    3931        32232 :   int list, ifc;
    3932        32232 :   enum omp_clause_code clause_code;
    3933        32232 :   gfc_omp_namelist *prev = NULL;
    3934        32232 :   gfc_se se;
    3935        32232 :   vec<gfc_symbol *> descriptors = vNULL;
    3936              : 
    3937        32232 :   if (clauses == NULL)
    3938              :     return NULL_TREE;
    3939              : 
    3940        32220 :   hash_map<gfc_symbol *, gfc_omp_namelist *> *sym_rooted_nl = NULL;
    3941              : 
    3942      1288800 :   for (list = 0; list < OMP_LIST_NUM; list++)
    3943              :     {
    3944      1256580 :       gfc_omp_namelist *n = clauses->lists[list];
    3945              : 
    3946      1256580 :       if (n == NULL)
    3947      1228365 :         continue;
    3948        28215 :       switch (list)
    3949              :         {
    3950         3850 :         case OMP_LIST_REDUCTION:
    3951         3850 :         case OMP_LIST_REDUCTION_INSCAN:
    3952         3850 :         case OMP_LIST_REDUCTION_TASK:
    3953         3850 :         case OMP_LIST_IN_REDUCTION:
    3954         3850 :         case OMP_LIST_TASK_REDUCTION:
    3955              :           /* An OpenACC async clause indicates the need to set reduction
    3956              :              arguments addressable, to allow asynchronous copy-out.  */
    3957         3850 :           omp_clauses = gfc_trans_omp_reduction_list (list, n, omp_clauses,
    3958         3850 :                                                       where, clauses->async);
    3959         3850 :           break;
    3960         6484 :         case OMP_LIST_PRIVATE:
    3961         6484 :           clause_code = OMP_CLAUSE_PRIVATE;
    3962         6484 :           goto add_clause;
    3963         1079 :         case OMP_LIST_SHARED:
    3964         1079 :           clause_code = OMP_CLAUSE_SHARED;
    3965         1079 :           goto add_clause;
    3966         1108 :         case OMP_LIST_FIRSTPRIVATE:
    3967         1108 :           clause_code = OMP_CLAUSE_FIRSTPRIVATE;
    3968         1108 :           goto add_clause;
    3969         1663 :         case OMP_LIST_LASTPRIVATE:
    3970         1663 :           clause_code = OMP_CLAUSE_LASTPRIVATE;
    3971         1663 :           goto add_clause;
    3972           96 :         case OMP_LIST_COPYIN:
    3973           96 :           clause_code = OMP_CLAUSE_COPYIN;
    3974           96 :           goto add_clause;
    3975           74 :         case OMP_LIST_COPYPRIVATE:
    3976           74 :           clause_code = OMP_CLAUSE_COPYPRIVATE;
    3977           74 :           goto add_clause;
    3978           61 :         case OMP_LIST_UNIFORM:
    3979           61 :           clause_code = OMP_CLAUSE_UNIFORM;
    3980           61 :           goto add_clause;
    3981           51 :         case OMP_LIST_USE_DEVICE:
    3982           51 :         case OMP_LIST_USE_DEVICE_PTR:
    3983           51 :           clause_code = OMP_CLAUSE_USE_DEVICE_PTR;
    3984           51 :           goto add_clause;
    3985          922 :         case OMP_LIST_USE_DEVICE_ADDR:
    3986          922 :           clause_code = OMP_CLAUSE_USE_DEVICE_ADDR;
    3987          922 :           goto add_clause;
    3988           43 :         case OMP_LIST_IS_DEVICE_PTR:
    3989           43 :           clause_code = OMP_CLAUSE_IS_DEVICE_PTR;
    3990           43 :           goto add_clause;
    3991          112 :         case OMP_LIST_HAS_DEVICE_ADDR:
    3992          112 :           clause_code = OMP_CLAUSE_HAS_DEVICE_ADDR;
    3993          112 :           goto add_clause;
    3994            2 :         case OMP_LIST_NONTEMPORAL:
    3995            2 :           clause_code = OMP_CLAUSE_NONTEMPORAL;
    3996            2 :           goto add_clause;
    3997            9 :         case OMP_LIST_SCAN_IN:
    3998            9 :           clause_code = OMP_CLAUSE_INCLUSIVE;
    3999            9 :           goto add_clause;
    4000            7 :         case OMP_LIST_SCAN_EX:
    4001            7 :           clause_code = OMP_CLAUSE_EXCLUSIVE;
    4002            7 :           goto add_clause;
    4003            4 :         case OMP_LIST_USE:
    4004            4 :           clause_code = OMP_CLAUSE_USE;
    4005            4 :           goto add_clause;
    4006           55 :         case OMP_LIST_INTEROP:
    4007           55 :           clause_code = OMP_CLAUSE_INTEROP;
    4008           55 :           goto add_clause;
    4009              : 
    4010        11770 :         add_clause:
    4011        11770 :           omp_clauses
    4012        11770 :             = gfc_trans_omp_variable_list (clause_code, n, omp_clauses,
    4013              :                                            declare_simd);
    4014        11770 :           break;
    4015              : 
    4016              :         case OMP_LIST_DESTROY:
    4017           12 :           for (; n != NULL; n = n->next)
    4018            9 :             if (n->sym->attr.referenced)
    4019              :               {
    4020            9 :                 tree t = gfc_trans_omp_variable (n->sym, declare_simd);
    4021            9 :                 if (t != error_mark_node)
    4022              :                   {
    4023            9 :                     tree node
    4024            9 :                       = build_omp_clause (input_location, OMP_CLAUSE_DESTROY);
    4025            9 :                     OMP_CLAUSE_DECL (node) = t;
    4026            9 :                     TREE_ADDRESSABLE (OMP_CLAUSE_DECL (node)) = 1;
    4027            9 :                     omp_clauses = gfc_trans_add_clause (node, omp_clauses);
    4028              :                   }
    4029              :               }
    4030              :           break;
    4031              : 
    4032              :         case OMP_LIST_INIT:
    4033              :           {
    4034              :             tree pref_type = NULL_TREE;
    4035              :             const char *last = NULL;
    4036           32 :             for (; n != NULL; n = n->next)
    4037           26 :               if (n->sym->attr.referenced)
    4038              :                 {
    4039           26 :                   tree t = gfc_trans_omp_variable (n->sym, false);
    4040           26 :                   if (t == error_mark_node)
    4041            0 :                     continue;
    4042           26 :                   tree node = build_omp_clause (input_location,
    4043              :                                                 OMP_CLAUSE_INIT);
    4044           26 :                   OMP_CLAUSE_DECL (node) = t;
    4045           26 :                   TREE_ADDRESSABLE (OMP_CLAUSE_DECL (node)) = 1;
    4046           26 :                   if (n->u.init.target)
    4047           19 :                     OMP_CLAUSE_INIT_TARGET (node) = 1;
    4048           26 :                   if (n->u.init.targetsync)
    4049           10 :                     OMP_CLAUSE_INIT_TARGETSYNC (node) = 1;
    4050           26 :                   if (last != n->u2.init_interop)
    4051              :                     {
    4052            6 :                       last = n->u2.init_interop;
    4053            6 :                       if (n->u2.init_interop == NULL)
    4054              :                         pref_type = NULL_TREE;
    4055              :                       else
    4056              :                         {
    4057            5 :                           pref_type = build_string (n->u.init.len,
    4058              :                                                     n->u2.init_interop);
    4059            5 :                           TREE_TYPE (pref_type)
    4060           10 :                             = build_array_type_nelts (unsigned_char_type_node,
    4061            5 :                                                       n->u.init.len);
    4062              :                         }
    4063              :                     }
    4064           26 :                   OMP_CLAUSE_INIT_PREFER_TYPE (node) = pref_type;
    4065           26 :                   omp_clauses = gfc_trans_add_clause (node, omp_clauses);
    4066              :                 }
    4067              :             break;
    4068              :           }
    4069              : 
    4070              :         case OMP_LIST_ALIGNED:
    4071          256 :           for (; n != NULL; n = n->next)
    4072          149 :             if (n->sym->attr.referenced || declare_simd)
    4073              :               {
    4074          149 :                 tree t = gfc_trans_omp_variable (n->sym, declare_simd);
    4075          149 :                 if (t != error_mark_node)
    4076              :                   {
    4077          149 :                     tree node = build_omp_clause (input_location,
    4078              :                                                   OMP_CLAUSE_ALIGNED);
    4079          149 :                     OMP_CLAUSE_DECL (node) = t;
    4080          149 :                     if (n->expr)
    4081              :                       {
    4082          148 :                         tree alignment_var;
    4083              : 
    4084          148 :                         if (declare_simd)
    4085            5 :                           alignment_var = gfc_conv_constant_to_tree (n->expr);
    4086              :                         else
    4087              :                           {
    4088          143 :                             gfc_init_se (&se, NULL);
    4089          143 :                             gfc_conv_expr (&se, n->expr);
    4090          143 :                             gfc_add_block_to_block (block, &se.pre);
    4091          143 :                             alignment_var = gfc_evaluate_now (se.expr, block);
    4092          143 :                             gfc_add_block_to_block (block, &se.post);
    4093              :                           }
    4094          148 :                         OMP_CLAUSE_ALIGNED_ALIGNMENT (node) = alignment_var;
    4095              :                       }
    4096          149 :                     omp_clauses = gfc_trans_add_clause (node, omp_clauses);
    4097              :                   }
    4098              :               }
    4099              :           break;
    4100              :         case OMP_LIST_ALLOCATE:
    4101              :           {
    4102              :             tree allocator_ = NULL_TREE;
    4103              :             gfc_expr *alloc_expr = NULL;
    4104          679 :             for (; n != NULL; n = n->next)
    4105          429 :               if (n->sym->attr.referenced)
    4106              :                 {
    4107          429 :                   tree t = gfc_trans_omp_variable (n->sym, false);
    4108          429 :                   if (t != error_mark_node)
    4109              :                     {
    4110          429 :                       tree node = build_omp_clause (input_location,
    4111              :                                                     OMP_CLAUSE_ALLOCATE);
    4112          429 :                       OMP_CLAUSE_DECL (node) = t;
    4113          429 :                       if (n->u2.allocator)
    4114              :                         {
    4115          294 :                           if (alloc_expr != n->u2.allocator)
    4116              :                             {
    4117          170 :                               gfc_init_se (&se, NULL);
    4118          170 :                               gfc_conv_expr (&se, n->u2.allocator);
    4119          170 :                               gfc_add_block_to_block (block, &se.pre);
    4120          170 :                               t = se.expr;
    4121          170 :                               if (DECL_P (t) && se.post.head == NULL_TREE)
    4122           22 :                                 allocator_ = (POINTER_TYPE_P (TREE_TYPE (t))
    4123           11 :                                               ? build_fold_indirect_ref (t): t);
    4124              :                               else
    4125          159 :                                 allocator_ = gfc_evaluate_now (t, block);
    4126          170 :                               gfc_add_block_to_block (block, &se.post);
    4127              :                             }
    4128          294 :                           OMP_CLAUSE_ALLOCATE_ALLOCATOR (node) = allocator_;
    4129              :                         }
    4130          429 :                       alloc_expr = n->u2.allocator;
    4131          429 :                       if (n->u.align)
    4132              :                         {
    4133           51 :                           tree align_;
    4134           51 :                           gfc_init_se (&se, NULL);
    4135           51 :                           gfc_conv_expr (&se, n->u.align);
    4136           51 :                           gcc_assert (CONSTANT_CLASS_P (se.expr)
    4137              :                                       && se.pre.head == NULL
    4138              :                                       && se.post.head == NULL);
    4139           51 :                           align_ = se.expr;
    4140           51 :                           OMP_CLAUSE_ALLOCATE_ALIGN (node) = align_;
    4141              :                         }
    4142          429 :                       omp_clauses = gfc_trans_add_clause (node, omp_clauses);
    4143              :                     }
    4144              :                 }
    4145              :               else
    4146            0 :                 alloc_expr = n->u2.allocator;
    4147              :             }
    4148              :           break;
    4149              :         case OMP_LIST_LINEAR:
    4150              :           {
    4151              :             gfc_expr *last_step_expr = NULL;
    4152              :             tree last_step = NULL_TREE;
    4153              :             bool last_step_parm = false;
    4154              : 
    4155         1288 :             for (; n != NULL; n = n->next)
    4156              :               {
    4157          795 :                 if (n->expr)
    4158              :                   {
    4159          776 :                     last_step_expr = n->expr;
    4160          776 :                     last_step = NULL_TREE;
    4161          776 :                     last_step_parm = false;
    4162              :                   }
    4163          795 :                 if (n->sym->attr.referenced || declare_simd)
    4164              :                   {
    4165          795 :                     tree t = gfc_trans_omp_variable (n->sym, declare_simd);
    4166          795 :                     if (t != error_mark_node)
    4167              :                       {
    4168          795 :                         tree node = build_omp_clause (input_location,
    4169              :                                                       OMP_CLAUSE_LINEAR);
    4170          795 :                         OMP_CLAUSE_DECL (node) = t;
    4171          795 :                         omp_clause_linear_kind kind;
    4172          795 :                         switch (n->u.linear.op)
    4173              :                           {
    4174              :                           case OMP_LINEAR_DEFAULT:
    4175              :                             kind = OMP_CLAUSE_LINEAR_DEFAULT;
    4176              :                             break;
    4177              :                           case OMP_LINEAR_REF:
    4178              :                             kind = OMP_CLAUSE_LINEAR_REF;
    4179              :                             break;
    4180              :                           case OMP_LINEAR_VAL:
    4181              :                             kind = OMP_CLAUSE_LINEAR_VAL;
    4182              :                             break;
    4183              :                           case OMP_LINEAR_UVAL:
    4184              :                             kind = OMP_CLAUSE_LINEAR_UVAL;
    4185              :                             break;
    4186            0 :                           default:
    4187            0 :                             gcc_unreachable ();
    4188              :                           }
    4189          795 :                         OMP_CLAUSE_LINEAR_KIND (node) = kind;
    4190          795 :                         OMP_CLAUSE_LINEAR_OLD_LINEAR_MODIFIER (node)
    4191          795 :                           = n->u.linear.old_modifier;
    4192          795 :                         if (last_step_expr && last_step == NULL_TREE)
    4193              :                           {
    4194          776 :                             if (!declare_simd)
    4195              :                               {
    4196          695 :                                 gfc_init_se (&se, NULL);
    4197          695 :                                 gfc_conv_expr (&se, last_step_expr);
    4198          695 :                                 gfc_add_block_to_block (block, &se.pre);
    4199          695 :                                 last_step = gfc_evaluate_now (se.expr, block);
    4200          695 :                                 gfc_add_block_to_block (block, &se.post);
    4201              :                               }
    4202           81 :                             else if (last_step_expr->expr_type == EXPR_VARIABLE)
    4203              :                               {
    4204            2 :                                 gfc_symbol *s = last_step_expr->symtree->n.sym;
    4205            2 :                                 last_step = gfc_trans_omp_variable (s, true);
    4206            2 :                                 last_step_parm = true;
    4207              :                               }
    4208              :                             else
    4209           79 :                               last_step
    4210           79 :                                 = gfc_conv_constant_to_tree (last_step_expr);
    4211              :                           }
    4212          795 :                         if (last_step_parm)
    4213              :                           {
    4214            2 :                             OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (node) = 1;
    4215            2 :                             OMP_CLAUSE_LINEAR_STEP (node) = last_step;
    4216              :                           }
    4217              :                         else
    4218              :                           {
    4219          793 :                             if (kind == OMP_CLAUSE_LINEAR_REF)
    4220              :                               {
    4221           34 :                                 tree type;
    4222           34 :                                 if (n->sym->attr.flavor == FL_PROCEDURE)
    4223              :                                   {
    4224            0 :                                     type = gfc_get_function_type (n->sym);
    4225            0 :                                     type = build_pointer_type (type);
    4226              :                                   }
    4227              :                                 else
    4228           34 :                                   type = gfc_sym_type (n->sym);
    4229           34 :                                 if (POINTER_TYPE_P (type))
    4230           34 :                                   type = TREE_TYPE (type);
    4231              :                                 /* Otherwise to be determined what exactly
    4232              :                                    should be done.  */
    4233           34 :                                 tree t = fold_convert (sizetype, last_step);
    4234           34 :                                 t = size_binop (MULT_EXPR, t,
    4235              :                                                 TYPE_SIZE_UNIT (type));
    4236           34 :                                 OMP_CLAUSE_LINEAR_STEP (node) = t;
    4237              :                               }
    4238              :                             else
    4239              :                               {
    4240          759 :                                 tree type
    4241          759 :                                   = gfc_typenode_for_spec (&n->sym->ts);
    4242          759 :                                 OMP_CLAUSE_LINEAR_STEP (node)
    4243         1518 :                                   = fold_convert (type, last_step);
    4244              :                               }
    4245              :                           }
    4246          795 :                         if (n->sym->attr.dimension || n->sym->attr.allocatable)
    4247          222 :                           OMP_CLAUSE_LINEAR_ARRAY (node) = 1;
    4248          795 :                         omp_clauses = gfc_trans_add_clause (node, omp_clauses);
    4249              :                       }
    4250              :                   }
    4251              :               }
    4252              :           }
    4253              :           break;
    4254              :         case OMP_LIST_AFFINITY:
    4255              :         case OMP_LIST_DEPEND:
    4256              :           iterator = NULL_TREE;
    4257              :           prev = NULL;
    4258              :           prev_clauses = omp_clauses;
    4259         1582 :           for (; n != NULL; n = n->next)
    4260              :             {
    4261          857 :               if (iterator && prev->u2.ns != n->u2.ns)
    4262              :                 {
    4263           12 :                   finish_iterator_group (list, &iter_block, tree_block,
    4264              :                                          iterator, omp_clauses, prev_clauses);
    4265           12 :                   prev_clauses = omp_clauses;
    4266           12 :                   iterator = NULL_TREE;
    4267              :                 }
    4268          857 :               if (n->u2.ns && (!prev || prev->u2.ns != n->u2.ns))
    4269              : 
    4270           46 :                 iterator = start_iterator_group (n->u2.ns, block, &iter_block,
    4271              :                                                  tree_block);
    4272          857 :               if (!iterator)
    4273          802 :                 gfc_init_block (&iter_block);
    4274          857 :               prev = n;
    4275          857 :               if (list == OMP_LIST_DEPEND
    4276          831 :                   && (n->u.depend_doacross_op == OMP_DOACROSS_SINK_FIRST
    4277          831 :                       || n->u.depend_doacross_op == OMP_DEPEND_SINK_FIRST))
    4278              :                 {
    4279          228 :                   tree vec = NULL_TREE;
    4280          228 :                   unsigned int i;
    4281          228 :                   bool is_depend
    4282              :                     = n->u.depend_doacross_op == OMP_DEPEND_SINK_FIRST;
    4283          228 :                   for (i = 0; ; i++)
    4284              :                     {
    4285         1219 :                       tree addend = integer_zero_node, t;
    4286         1219 :                       bool neg = false;
    4287         1219 :                       if (n->sym && n->expr)
    4288              :                         {
    4289          558 :                           addend = gfc_conv_constant_to_tree (n->expr);
    4290          558 :                           if (TREE_CODE (addend) == INTEGER_CST
    4291          558 :                               && tree_int_cst_sgn (addend) == -1)
    4292              :                             {
    4293          407 :                               neg = true;
    4294          407 :                               addend = const_unop (NEGATE_EXPR,
    4295          407 :                                                    TREE_TYPE (addend), addend);
    4296              :                             }
    4297              :                         }
    4298              : 
    4299         1219 :                       if (n->sym == NULL)
    4300            0 :                         t = null_pointer_node;  /* "omp_cur_iteration - 1".  */
    4301              :                       else
    4302         1219 :                         t = gfc_trans_omp_variable (n->sym, false);
    4303         1219 :                       if (t != error_mark_node)
    4304              :                         {
    4305         1219 :                           if (i < vec_safe_length (doacross_steps)
    4306          426 :                               && !integer_zerop (addend)
    4307          630 :                               && (*doacross_steps)[i])
    4308              :                             {
    4309          204 :                               tree step = (*doacross_steps)[i];
    4310          204 :                               addend = fold_convert (TREE_TYPE (step), addend);
    4311          204 :                               addend = build2 (TRUNC_DIV_EXPR,
    4312          204 :                                                TREE_TYPE (step), addend, step);
    4313              :                             }
    4314         1219 :                           vec = tree_cons (addend, t, vec);
    4315         1219 :                           if (neg)
    4316          407 :                             OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (vec) = 1;
    4317              :                         }
    4318         1219 :                       if (n->next == NULL
    4319         1057 :                           || n->next->u.depend_doacross_op != OMP_DOACROSS_SINK)
    4320              :                         break;
    4321          991 :                       n = n->next;
    4322          991 :                     }
    4323          228 :                   if (vec == NULL_TREE)
    4324            0 :                     continue;
    4325              : 
    4326          228 :                   tree node = build_omp_clause (input_location,
    4327              :                                                 OMP_CLAUSE_DOACROSS);
    4328          228 :                   OMP_CLAUSE_DOACROSS_KIND (node) = OMP_CLAUSE_DOACROSS_SINK;
    4329          228 :                   OMP_CLAUSE_DOACROSS_DEPEND (node) = is_depend;
    4330          228 :                   OMP_CLAUSE_DECL (node) = nreverse (vec);
    4331          228 :                   omp_clauses = gfc_trans_add_clause (node, omp_clauses);
    4332          228 :                   continue;
    4333          228 :                 }
    4334              : 
    4335          629 :               if (n->sym && !n->sym->attr.referenced)
    4336            0 :                 continue;
    4337              : 
    4338          655 :               tree node = build_omp_clause (input_location,
    4339              :                                             list == OMP_LIST_DEPEND
    4340              :                                             ? OMP_CLAUSE_DEPEND
    4341              :                                             : OMP_CLAUSE_AFFINITY);
    4342          629 :               if (n->sym == NULL)  /* omp_all_memory  */
    4343            9 :                 OMP_CLAUSE_DECL (node) = null_pointer_node;
    4344          620 :               else if (n->expr == NULL || n->expr->ref->u.ar.type == AR_FULL)
    4345              :                 {
    4346          404 :                   tree decl = gfc_trans_omp_variable (n->sym, false);
    4347          404 :                   if (gfc_omp_privatize_by_reference (decl))
    4348           62 :                     decl = build_fold_indirect_ref (decl);
    4349          404 :                   if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
    4350              :                     {
    4351           23 :                       decl = gfc_conv_descriptor_data_get (decl);
    4352           23 :                       gcc_assert (POINTER_TYPE_P (TREE_TYPE (decl)));
    4353           23 :                       decl = build_fold_indirect_ref (decl);
    4354              :                     }
    4355          381 :                   else if (n->sym->attr.allocatable || n->sym->attr.pointer)
    4356           22 :                     decl = build_fold_indirect_ref (decl);
    4357          359 :                   else if (DECL_P (decl))
    4358          326 :                     TREE_ADDRESSABLE (decl) = 1;
    4359          404 :                   OMP_CLAUSE_DECL (node) = decl;
    4360          404 :                 }
    4361              :               else
    4362              :                 {
    4363          216 :                   tree ptr;
    4364          216 :                   gfc_init_se (&se, NULL);
    4365              :                   /* The first ref can be an element selection on the base
    4366              :                      object while the full expression still denotes an array,
    4367              :                      e.g. x(j)%a.  Pick the lowering path from the overall
    4368              :                      expression rank, not from the first REF_ARRAY.  */
    4369          216 :                   if (n->expr->rank == 0)
    4370              :                     {
    4371          135 :                       gfc_conv_expr_reference (&se, n->expr);
    4372          135 :                       ptr = se.expr;
    4373              :                     }
    4374              :                   else
    4375              :                     {
    4376           81 :                       gfc_conv_expr_descriptor (&se, n->expr);
    4377           81 :                       ptr = gfc_conv_array_data (se.expr);
    4378              :                     }
    4379          216 :                   gfc_add_block_to_block (&iter_block, &se.pre);
    4380          216 :                   gfc_add_block_to_block (&iter_block, &se.post);
    4381          216 :                   gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
    4382          216 :                   OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr);
    4383              :                 }
    4384          629 :               if (list == OMP_LIST_DEPEND)
    4385          603 :                 switch (n->u.depend_doacross_op)
    4386              :                   {
    4387          228 :                   case OMP_DEPEND_IN:
    4388          228 :                     OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_IN;
    4389          228 :                     break;
    4390          258 :                   case OMP_DEPEND_OUT:
    4391          258 :                     OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_OUT;
    4392          258 :                     break;
    4393           55 :                   case OMP_DEPEND_INOUT:
    4394           55 :                     OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_INOUT;
    4395           55 :                     break;
    4396            9 :                   case OMP_DEPEND_INOUTSET:
    4397            9 :                     OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_INOUTSET;
    4398            9 :                     break;
    4399           15 :                   case OMP_DEPEND_MUTEXINOUTSET:
    4400           15 :                     OMP_CLAUSE_DEPEND_KIND (node)
    4401           15 :                       = OMP_CLAUSE_DEPEND_MUTEXINOUTSET;
    4402           15 :                     break;
    4403           38 :                   case OMP_DEPEND_DEPOBJ:
    4404           38 :                     OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_DEPOBJ;
    4405           38 :                     break;
    4406            0 :                   default:
    4407            0 :                     gcc_unreachable ();
    4408              :                   }
    4409          629 :               if (!iterator)
    4410          574 :                 gfc_add_block_to_block (block, &iter_block);
    4411          629 :               omp_clauses = gfc_trans_add_clause (node, omp_clauses);
    4412              :             }
    4413          725 :           if (iterator)
    4414           34 :             finish_iterator_group (list, &iter_block, tree_block,
    4415              :                                    iterator, omp_clauses, prev_clauses);
    4416              :           break;
    4417              :         case OMP_LIST_MAP:
    4418              :           iterator = NULL_TREE;
    4419              :           prev = NULL;
    4420              :           prev_clauses = omp_clauses;
    4421        25203 :           for (; n != NULL; n = n->next)
    4422              :             {
    4423        16007 :               if (!openacc)
    4424              :                 {
    4425         7423 :                   if (n->u3.udm)
    4426            7 :                     gfc_error ("Sorry, declared mapper %qs, used for %qs at %L, "
    4427              :                                "is not yet supported",
    4428            7 :                                n->u3.udm->requested_mapper_id[0] != '\0'
    4429              :                                ? n->u3.udm->requested_mapper_id : "default",
    4430            7 :                                n->sym->name, &n->where);
    4431              : 
    4432              :                   // Remove duplicates
    4433         7423 :                   bool skip = false;
    4434        17113 :                   for (gfc_omp_namelist *n2 = n->next; n2 != NULL;
    4435         9690 :                        n2 = n2->next)
    4436              :                     {
    4437         9959 :                       if (n2->sym == n->sym
    4438         9959 :                           && gfc_dep_compare_expr (n2->expr, n->expr) == 0)
    4439              :                         {
    4440          315 :                           if (n2->u.map.op == n->u.map.op)
    4441              :                             {
    4442              :                               skip = true;
    4443              :                               break;
    4444              :                             }
    4445          297 :                           else if ((n2->u.map.op & ~OMP_MAP_TOFROM)
    4446          297 :                                    == (n->u.map.op & ~OMP_MAP_TOFROM))
    4447              :                             {
    4448          251 :                               n2->u.map.op = (enum gfc_omp_map_op) (
    4449          251 :                                 n->u.map.op | n2->u.map.op);
    4450          251 :                               skip = true;
    4451          251 :                               break;
    4452              :                             }
    4453              :                         }
    4454              :                     }
    4455         7423 :                   if (skip)
    4456          833 :                     continue;
    4457              :                 }
    4458              : 
    4459        15738 :               if (!n->sym->attr.referenced
    4460        15738 :                   || n->sym->attr.flavor == FL_PARAMETER)
    4461            9 :                 continue;
    4462              : 
    4463        15729 :               if (iterator && prev->u2.ns != n->u2.ns)
    4464              :                 {
    4465           25 :                   finish_iterator_group (list, &iter_block, tree_block,
    4466              :                                          iterator, omp_clauses, prev_clauses);
    4467           25 :                   prev_clauses = omp_clauses;
    4468           25 :                   iterator = NULL_TREE;
    4469              :                 }
    4470        15729 :               if (n->u2.ns && (!prev || prev->u2.ns != n->u2.ns))
    4471              :                 {
    4472           37 :                   iterator = start_iterator_group (n->u2.ns, block,
    4473              :                                                    &iter_block, tree_block);
    4474           37 :                   prev_clauses = omp_clauses;
    4475              :                 }
    4476        15729 :               if (!iterator)
    4477        15690 :                 gfc_init_block (&iter_block);
    4478        15729 :               prev = n;
    4479              : 
    4480        15729 :               location_t map_loc = gfc_get_location (&n->where);
    4481        15729 :               bool always_modifier = false;
    4482        15729 :               tree node = build_omp_clause (map_loc, OMP_CLAUSE_MAP);
    4483        15729 :               tree node2 = NULL_TREE;
    4484        15729 :               tree node3 = NULL_TREE;
    4485        15729 :               tree node4 = NULL_TREE;
    4486        15729 :               tree node5 = NULL_TREE;
    4487              : 
    4488              :               /* OpenMP: automatically map pointer targets with the pointer;
    4489              :                  hence, always update the descriptor/pointer itself.  */
    4490        15729 :               if (!openacc
    4491        15729 :                   && ((n->expr == NULL && n->sym->attr.pointer)
    4492        14941 :                       || (n->expr && gfc_expr_attr (n->expr).pointer)))
    4493         1393 :                 always_modifier = true;
    4494              : 
    4495        15729 :               if (n->u.map.readonly)
    4496           22 :                 OMP_CLAUSE_MAP_READONLY (node) = 1;
    4497              : 
    4498        15729 :               switch (n->u.map.op)
    4499              :                 {
    4500         1098 :                 case OMP_MAP_ALLOC:
    4501         1098 :                   OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALLOC);
    4502         1098 :                   break;
    4503           64 :                 case OMP_MAP_IF_PRESENT:
    4504           64 :                   OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_IF_PRESENT);
    4505           64 :                   break;
    4506           66 :                 case OMP_MAP_ATTACH:
    4507           66 :                   OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ATTACH);
    4508           66 :                   break;
    4509         4347 :                 case OMP_MAP_TO:
    4510         4347 :                   OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_TO);
    4511         4347 :                   break;
    4512         3110 :                 case OMP_MAP_FROM:
    4513         3110 :                   OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FROM);
    4514         3110 :                   break;
    4515         4526 :                 case OMP_MAP_TOFROM:
    4516         4526 :                   OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_TOFROM);
    4517         4526 :                   break;
    4518           35 :                 case OMP_MAP_ALWAYS_TO:
    4519           35 :                   always_modifier = true;
    4520           35 :                   OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_TO);
    4521           35 :                   break;
    4522           17 :                 case OMP_MAP_ALWAYS_FROM:
    4523           17 :                   always_modifier = true;
    4524           17 :                   OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_FROM);
    4525           17 :                   break;
    4526          171 :                 case OMP_MAP_ALWAYS_TOFROM:
    4527          171 :                   always_modifier = true;
    4528          171 :                   OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_TOFROM);
    4529          171 :                   break;
    4530           15 :                 case OMP_MAP_PRESENT_ALLOC:
    4531           15 :                   OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_PRESENT_ALLOC);
    4532           15 :                   break;
    4533           14 :                 case OMP_MAP_PRESENT_TO:
    4534           14 :                   OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_PRESENT_TO);
    4535           14 :                   break;
    4536            5 :                 case OMP_MAP_PRESENT_FROM:
    4537            5 :                   OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_PRESENT_FROM);
    4538            5 :                   break;
    4539            3 :                 case OMP_MAP_PRESENT_TOFROM:
    4540            3 :                   OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_PRESENT_TOFROM);
    4541            3 :                   break;
    4542           10 :                 case OMP_MAP_ALWAYS_PRESENT_TO:
    4543           10 :                   always_modifier = true;
    4544           10 :                   OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_PRESENT_TO);
    4545           10 :                   break;
    4546            4 :                 case OMP_MAP_ALWAYS_PRESENT_FROM:
    4547            4 :                   always_modifier = true;
    4548            4 :                   OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_PRESENT_FROM);
    4549            4 :                   break;
    4550            2 :                 case OMP_MAP_ALWAYS_PRESENT_TOFROM:
    4551            2 :                   always_modifier = true;
    4552            2 :                   OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_PRESENT_TOFROM);
    4553            2 :                   break;
    4554          457 :                 case OMP_MAP_RELEASE:
    4555          457 :                   OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_RELEASE);
    4556          457 :                   break;
    4557           80 :                 case OMP_MAP_DELETE:
    4558           80 :                   OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_DELETE);
    4559           80 :                   break;
    4560           44 :                 case OMP_MAP_DETACH:
    4561           44 :                   OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_DETACH);
    4562           44 :                   break;
    4563           64 :                 case OMP_MAP_FORCE_ALLOC:
    4564           64 :                   OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_ALLOC);
    4565           64 :                   break;
    4566          465 :                 case OMP_MAP_FORCE_TO:
    4567          465 :                   OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_TO);
    4568          465 :                   break;
    4569          577 :                 case OMP_MAP_FORCE_FROM:
    4570          577 :                   OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_FROM);
    4571          577 :                   break;
    4572            0 :                 case OMP_MAP_FORCE_TOFROM:
    4573            0 :                   OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_TOFROM);
    4574            0 :                   break;
    4575          545 :                 case OMP_MAP_FORCE_PRESENT:
    4576          545 :                   OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_PRESENT);
    4577          545 :                   break;
    4578           10 :                 case OMP_MAP_FORCE_DEVICEPTR:
    4579           10 :                   OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_DEVICEPTR);
    4580           10 :                   break;
    4581            0 :                 default:
    4582            0 :                   gcc_unreachable ();
    4583              :                 }
    4584              : 
    4585        15729 :               tree decl = gfc_trans_omp_variable (n->sym, false);
    4586        15729 :               if (DECL_P (decl))
    4587        15729 :                 TREE_ADDRESSABLE (decl) = 1;
    4588              : 
    4589        15729 :               gfc_ref *lastref = NULL;
    4590              : 
    4591        15729 :               if (n->expr)
    4592        15022 :                 for (gfc_ref *ref = n->expr->ref; ref; ref = ref->next)
    4593         9215 :                   if (ref->type == REF_COMPONENT || ref->type == REF_ARRAY)
    4594         9215 :                     lastref = ref;
    4595              : 
    4596         5807 :               bool allocatable = false, pointer = false;
    4597              : 
    4598         5807 :               if (lastref && lastref->type == REF_COMPONENT)
    4599              :                 {
    4600          457 :                   gfc_component *c = lastref->u.c.component;
    4601              : 
    4602          457 :                   if (c->ts.type == BT_CLASS)
    4603              :                     {
    4604           24 :                       pointer = CLASS_DATA (c)->attr.class_pointer;
    4605           24 :                       allocatable = CLASS_DATA (c)->attr.allocatable;
    4606              :                     }
    4607              :                   else
    4608              :                     {
    4609          433 :                       pointer = c->attr.pointer;
    4610          433 :                       allocatable = c->attr.allocatable;
    4611              :                     }
    4612              :                 }
    4613              : 
    4614        15729 :               if (n->expr == NULL
    4615         5807 :                   || (n->expr->ref->type == REF_ARRAY
    4616         3677 :                       && n->expr->ref->u.ar.type == AR_FULL))
    4617              :                 {
    4618         9922 :                   gomp_map_kind map_kind;
    4619         9922 :                   tree type = TREE_TYPE (decl);
    4620         9922 :                   if (n->sym->ts.type == BT_CHARACTER
    4621          218 :                       && n->sym->ts.deferred
    4622           92 :                       && (n->sym->attr.omp_declare_target
    4623           84 :                           || n->sym->attr.omp_declare_target_link
    4624           84 :                           || n->sym->attr.omp_declare_target_local)
    4625            8 :                       && (always_modifier || n->sym->attr.pointer)
    4626            8 :                       && op != EXEC_OMP_TARGET_EXIT_DATA
    4627            4 :                       && n->u.map.op != OMP_MAP_DELETE
    4628            4 :                       && n->u.map.op != OMP_MAP_RELEASE)
    4629              :                     {
    4630            4 :                       gcc_assert (n->sym->ts.u.cl->backend_decl);
    4631            4 :                       node5 = build_omp_clause (map_loc, OMP_CLAUSE_MAP);
    4632            4 :                       OMP_CLAUSE_SET_MAP_KIND (node5, GOMP_MAP_ALWAYS_TO);
    4633            4 :                       OMP_CLAUSE_DECL (node5) = n->sym->ts.u.cl->backend_decl;
    4634            4 :                       OMP_CLAUSE_SIZE (node5)
    4635            8 :                         = TYPE_SIZE_UNIT (gfc_charlen_type_node);
    4636              :                     }
    4637              : 
    4638         9922 :                   tree present = gfc_omp_check_optional_argument (decl, true);
    4639         9922 :                   if (openacc && n->sym->ts.type == BT_CLASS)
    4640              :                     {
    4641           60 :                       if (n->sym->attr.optional)
    4642            0 :                         sorry_at (gfc_get_location (&n->where),
    4643              :                                   "optional class parameter");
    4644           60 :                       tree ptr = gfc_class_data_get (decl);
    4645           60 :                       ptr = build_fold_indirect_ref (ptr);
    4646           60 :                       OMP_CLAUSE_DECL (node) = ptr;
    4647           60 :                       OMP_CLAUSE_SIZE (node) = gfc_class_vtab_size_get (decl);
    4648           60 :                       node2 = build_omp_clause (map_loc, OMP_CLAUSE_MAP);
    4649           60 :                       OMP_CLAUSE_SET_MAP_KIND (node2, GOMP_MAP_ATTACH_DETACH);
    4650           60 :                       OMP_CLAUSE_DECL (node2) = gfc_class_data_get (decl);
    4651           60 :                       OMP_CLAUSE_SIZE (node2) = size_int (0);
    4652           60 :                       goto finalize_map_clause;
    4653              :                     }
    4654         9862 :                   else if (POINTER_TYPE_P (type)
    4655         9862 :                            && (gfc_omp_privatize_by_reference (decl)
    4656          508 :                                || GFC_DECL_GET_SCALAR_POINTER (decl)
    4657          323 :                                || GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
    4658           84 :                                || GFC_DECL_CRAY_POINTEE (decl)
    4659           84 :                                || GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (type))
    4660           84 :                                || (n->sym->ts.type == BT_DERIVED
    4661            8 :                                    && (n->sym->ts.u.derived->ts.f90_type
    4662              :                                        != BT_VOID))))
    4663              :                     {
    4664         3445 :                       tree orig_decl = decl;
    4665         3445 :                       bool bare_attach_detach
    4666              :                         = (openacc
    4667         1252 :                            && (n->u.map.op == OMP_MAP_ATTACH
    4668         1252 :                                || n->u.map.op == OMP_MAP_DETACH)
    4669            4 :                            && !GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl))
    4670         3449 :                            && !(POINTER_TYPE_P (TREE_TYPE (decl))
    4671            4 :                                 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE
    4672         3445 :                                                           (TREE_TYPE (decl)))));
    4673              : 
    4674              :                       /* For nonallocatable, nonpointer arrays, a temporary
    4675              :                          variable is generated, but this one is only defined if
    4676              :                          the variable is present; hence, we now set it to NULL
    4677              :                          to avoid accessing undefined variables.  We cannot use
    4678              :                          a temporary variable here as otherwise the replacement
    4679              :                          of the variables in omp-low.cc will not work.  */
    4680         3445 :                       if (present && GFC_ARRAY_TYPE_P (type))
    4681              :                         {
    4682          284 :                           tree tmp = fold_build2_loc (input_location,
    4683              :                                                       MODIFY_EXPR,
    4684              :                                                       void_type_node, decl,
    4685              :                                                       null_pointer_node);
    4686          284 :                           tree cond = fold_build1_loc (input_location,
    4687              :                                                        TRUTH_NOT_EXPR,
    4688              :                                                        boolean_type_node,
    4689              :                                                        present);
    4690          284 :                           gfc_add_expr_to_block (&iter_block,
    4691              :                                                  build3_loc (input_location,
    4692              :                                                              COND_EXPR,
    4693              :                                                              void_type_node,
    4694              :                                                              cond, tmp,
    4695              :                                                              NULL_TREE));
    4696              :                         }
    4697              :                       /* Bare OpenACC attach/detach on scalar pointer-like
    4698              :                          variables wants a single attach operation on the
    4699              :                          pointer itself, not a standalone pointer-mapping
    4700              :                          node.  Component and descriptor cases have dedicated
    4701              :                          handling below; this covers the plain scalar path.  */
    4702         3445 :                       if (bare_attach_detach)
    4703              :                         {
    4704            4 :                           decl = build_fold_indirect_ref (decl);
    4705            4 :                           OMP_CLAUSE_DECL (node) = build_fold_addr_expr (decl);
    4706            4 :                           OMP_CLAUSE_SIZE (node) = size_zero_node;
    4707            4 :                           goto finalize_map_clause;
    4708              :                         }
    4709              :                       /* For descriptor types, the unmapping happens below.  */
    4710         3441 :                       if (op != EXEC_OMP_TARGET_EXIT_DATA
    4711         3441 :                           || !GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
    4712              :                         {
    4713         3441 :                           enum gomp_map_kind gmk = GOMP_MAP_POINTER;
    4714         3441 :                           if (op == EXEC_OMP_TARGET_EXIT_DATA
    4715           73 :                               && n->u.map.op == OMP_MAP_DELETE)
    4716              :                             gmk = GOMP_MAP_DELETE;
    4717           62 :                           else if (op == EXEC_OMP_TARGET_EXIT_DATA)
    4718           62 :                             gmk = GOMP_MAP_RELEASE;
    4719         3441 :                           tree size;
    4720         3441 :                           if (gmk == GOMP_MAP_RELEASE || gmk == GOMP_MAP_DELETE)
    4721           73 :                             size = TYPE_SIZE_UNIT (TREE_TYPE (decl));
    4722              :                           else
    4723         3368 :                             size = size_int (0);
    4724         3441 :                           node4 = build_omp_clause (map_loc, OMP_CLAUSE_MAP);
    4725         3441 :                           OMP_CLAUSE_SET_MAP_KIND (node4, gmk);
    4726         3441 :                           OMP_CLAUSE_DECL (node4) = decl;
    4727         3441 :                           OMP_CLAUSE_SIZE (node4) = size;
    4728              :                         }
    4729         3441 :                       decl = build_fold_indirect_ref (decl);
    4730         3441 :                       if ((TREE_CODE (TREE_TYPE (orig_decl)) == REFERENCE_TYPE
    4731         2214 :                            || gfc_omp_is_optional_argument (orig_decl))
    4732         4493 :                           && (GFC_DECL_GET_SCALAR_POINTER (orig_decl)
    4733         2109 :                               || GFC_DECL_GET_SCALAR_ALLOCATABLE (orig_decl)))
    4734              :                         {
    4735          408 :                           enum gomp_map_kind gmk;
    4736          408 :                           if (op == EXEC_OMP_TARGET_EXIT_DATA
    4737            8 :                               && n->u.map.op == OMP_MAP_DELETE)
    4738              :                             gmk = GOMP_MAP_DELETE;
    4739            6 :                           else if (op == EXEC_OMP_TARGET_EXIT_DATA)
    4740              :                             gmk = GOMP_MAP_RELEASE;
    4741              :                           else
    4742              :                             gmk = GOMP_MAP_POINTER;
    4743          408 :                           tree size;
    4744          408 :                           if (gmk == GOMP_MAP_RELEASE || gmk == GOMP_MAP_DELETE)
    4745            8 :                             size = TYPE_SIZE_UNIT (TREE_TYPE (decl));
    4746              :                           else
    4747          400 :                             size = size_int (0);
    4748          408 :                           node3 = build_omp_clause (map_loc, OMP_CLAUSE_MAP);
    4749          408 :                           OMP_CLAUSE_SET_MAP_KIND (node3, gmk);
    4750          408 :                           OMP_CLAUSE_DECL (node3) = decl;
    4751          408 :                           OMP_CLAUSE_SIZE (node3) = size;
    4752          408 :                           decl = build_fold_indirect_ref (decl);
    4753              :                         }
    4754              :                     }
    4755         9858 :                   if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
    4756              :                     {
    4757         1407 :                       tree type = TREE_TYPE (decl);
    4758         1407 :                       tree ptr = gfc_conv_descriptor_data_get (decl);
    4759         1407 :                       if (present)
    4760          309 :                         ptr = gfc_build_cond_assign_expr (&iter_block,
    4761              :                                                           present, ptr,
    4762              :                                                           null_pointer_node);
    4763         1407 :                       gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
    4764         1407 :                       ptr = build_fold_indirect_ref (ptr);
    4765         1407 :                       OMP_CLAUSE_DECL (node) = ptr;
    4766         1407 :                       node2 = build_omp_clause (map_loc, OMP_CLAUSE_MAP);
    4767         1407 :                       OMP_CLAUSE_DECL (node2) = decl;
    4768         1407 :                       OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type);
    4769         1407 :                       if (n->u.map.op == OMP_MAP_DELETE)
    4770              :                         map_kind = GOMP_MAP_DELETE;
    4771         1380 :                       else if (op == EXEC_OMP_TARGET_EXIT_DATA
    4772         1317 :                                || n->u.map.op == OMP_MAP_RELEASE)
    4773              :                         map_kind = GOMP_MAP_RELEASE;
    4774              :                       else
    4775         1407 :                         map_kind = GOMP_MAP_TO_PSET;
    4776         1407 :                       OMP_CLAUSE_SET_MAP_KIND (node2, map_kind);
    4777              : 
    4778         1407 :                       if (op != EXEC_OMP_TARGET_EXIT_DATA
    4779         1317 :                           && n->u.map.op != OMP_MAP_DELETE
    4780         1317 :                           && n->u.map.op != OMP_MAP_RELEASE)
    4781              :                         {
    4782         1269 :                           node3 = build_omp_clause (map_loc, OMP_CLAUSE_MAP);
    4783         1269 :                           if (present)
    4784              :                             {
    4785          309 :                               ptr = gfc_conv_descriptor_data_get (decl);
    4786          309 :                               ptr = gfc_build_addr_expr (NULL, ptr);
    4787          309 :                               ptr = gfc_build_cond_assign_expr (
    4788              :                                 &iter_block, present, ptr, null_pointer_node);
    4789          309 :                               ptr = build_fold_indirect_ref (ptr);
    4790          309 :                               OMP_CLAUSE_DECL (node3) = ptr;
    4791              :                             }
    4792              :                           else
    4793          960 :                             OMP_CLAUSE_DECL (node3)
    4794         1920 :                               = gfc_conv_descriptor_data_get (decl);
    4795         1269 :                           OMP_CLAUSE_SIZE (node3) = size_int (0);
    4796              : 
    4797         1269 :                           if (n->u.map.op == OMP_MAP_ATTACH)
    4798              :                             {
    4799              :                               /* Standalone attach clauses used with arrays with
    4800              :                                  descriptors must copy the descriptor to the
    4801              :                                  target, else they won't have anything to
    4802              :                                  perform the attachment onto (see OpenACC 2.6,
    4803              :                                  "2.6.3. Data Structures with Pointers").  */
    4804            9 :                               OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_ATTACH);
    4805              :                               /* We don't want to map PTR at all in this case,
    4806              :                                  so delete its node and shuffle the others
    4807              :                                  down.  */
    4808            9 :                               node = node2;
    4809            9 :                               node2 = node3;
    4810            9 :                               node3 = NULL;
    4811            9 :                               goto finalize_map_clause;
    4812              :                             }
    4813         1260 :                           else if (n->u.map.op == OMP_MAP_DETACH)
    4814              :                             {
    4815            4 :                               OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_DETACH);
    4816              :                               /* Similarly to above, we don't want to unmap PTR
    4817              :                                  here.  */
    4818            4 :                               node = node2;
    4819            4 :                               node2 = node3;
    4820            4 :                               node3 = NULL;
    4821            4 :                               goto finalize_map_clause;
    4822              :                             }
    4823              :                           else
    4824         2042 :                             OMP_CLAUSE_SET_MAP_KIND (node3,
    4825              :                                                      always_modifier
    4826              :                                                      ? GOMP_MAP_ALWAYS_POINTER
    4827              :                                                      : GOMP_MAP_POINTER);
    4828              :                         }
    4829              : 
    4830              :                       /* We have to check for n->sym->attr.dimension because
    4831              :                          of scalar coarrays.  */
    4832         1394 :                       if ((n->sym->attr.pointer || n->sym->attr.allocatable)
    4833         1394 :                           && n->sym->attr.dimension)
    4834              :                         {
    4835         1394 :                           stmtblock_t cond_block;
    4836         1394 :                           tree size
    4837         1394 :                             = gfc_create_var (gfc_array_index_type, NULL);
    4838         1394 :                           tree tem, then_b, else_b, zero, cond;
    4839              : 
    4840         1394 :                           gfc_init_block (&cond_block);
    4841         1394 :                           tem
    4842         2788 :                             = gfc_full_array_size (&cond_block, decl,
    4843         1394 :                                                    GFC_TYPE_ARRAY_RANK (type));
    4844         1394 :                           tree elemsz;
    4845         1394 :                           if (n->sym->ts.type == BT_CHARACTER
    4846           52 :                               && n->sym->ts.deferred)
    4847              :                             {
    4848           44 :                               tree len = n->sym->ts.u.cl->backend_decl;
    4849           44 :                               len = fold_convert (size_type_node, len);
    4850           44 :                               elemsz = gfc_get_char_type (n->sym->ts.kind);
    4851           44 :                               elemsz = TYPE_SIZE_UNIT (elemsz);
    4852           44 :                               elemsz = fold_build2 (MULT_EXPR, size_type_node,
    4853              :                                                     len, elemsz);
    4854           44 :                             }
    4855              :                           else
    4856         1350 :                             elemsz
    4857         1350 :                               = TYPE_SIZE_UNIT (gfc_get_element_type (type));
    4858         1394 :                           elemsz = fold_convert (gfc_array_index_type, elemsz);
    4859         1394 :                           tem = fold_build2 (MULT_EXPR, gfc_array_index_type,
    4860              :                                              tem, elemsz);
    4861         1394 :                           gfc_add_modify (&cond_block, size, tem);
    4862         1394 :                           then_b = gfc_finish_block (&cond_block);
    4863         1394 :                           gfc_init_block (&cond_block);
    4864         1394 :                           zero = build_int_cst (gfc_array_index_type, 0);
    4865         1394 :                           gfc_add_modify (&cond_block, size, zero);
    4866         1394 :                           else_b = gfc_finish_block (&cond_block);
    4867         1394 :                           tem = gfc_conv_descriptor_data_get (decl);
    4868         1394 :                           tem = fold_convert (pvoid_type_node, tem);
    4869         1394 :                           cond = fold_build2_loc (input_location, NE_EXPR,
    4870              :                                                   boolean_type_node,
    4871              :                                                   tem, null_pointer_node);
    4872         1394 :                           if (present)
    4873          309 :                             cond = fold_build2_loc (input_location,
    4874              :                                                     TRUTH_ANDIF_EXPR,
    4875              :                                                     boolean_type_node,
    4876              :                                                     present, cond);
    4877         1394 :                           gfc_add_expr_to_block (&iter_block,
    4878              :                                                  build3_loc (input_location,
    4879              :                                                              COND_EXPR,
    4880              :                                                              void_type_node,
    4881              :                                                              cond, then_b,
    4882              :                                                              else_b));
    4883         1394 :                           OMP_CLAUSE_SIZE (node) = size;
    4884         1394 :                         }
    4885            0 :                       else if (n->sym->attr.dimension)
    4886              :                         {
    4887            0 :                           stmtblock_t cond_block;
    4888            0 :                           gfc_init_block (&cond_block);
    4889            0 :                           tree size = gfc_full_array_size (&cond_block, decl,
    4890            0 :                                         GFC_TYPE_ARRAY_RANK (type));
    4891            0 :                           tree elemsz
    4892            0 :                             = TYPE_SIZE_UNIT (gfc_get_element_type (type));
    4893            0 :                           elemsz = fold_convert (gfc_array_index_type, elemsz);
    4894            0 :                           size = fold_build2 (MULT_EXPR, gfc_array_index_type,
    4895              :                                               size, elemsz);
    4896            0 :                           size = gfc_evaluate_now (size, &cond_block);
    4897            0 :                           if (present)
    4898              :                             {
    4899            0 :                               tree var = gfc_create_var (gfc_array_index_type,
    4900              :                                                          NULL);
    4901            0 :                               gfc_add_modify (&cond_block, var, size);
    4902            0 :                               tree cond_body = gfc_finish_block (&cond_block);
    4903            0 :                               tree cond = build3_loc (input_location, COND_EXPR,
    4904              :                                                       void_type_node, present,
    4905              :                                                       cond_body, NULL_TREE);
    4906            0 :                               gfc_add_expr_to_block (&iter_block, cond);
    4907            0 :                               OMP_CLAUSE_SIZE (node) = var;
    4908              :                             }
    4909              :                           else
    4910              :                             {
    4911            0 :                               gfc_add_block_to_block (&iter_block, &cond_block);
    4912            0 :                               OMP_CLAUSE_SIZE (node) = size;
    4913              :                             }
    4914              :                         }
    4915              :                     }
    4916         8451 :                   else if (present
    4917          845 :                            && INDIRECT_REF_P (decl)
    4918         9194 :                            && INDIRECT_REF_P (TREE_OPERAND (decl, 0)))
    4919              :                     {
    4920              :                       /* A single indirectref is handled by the middle end.  */
    4921          228 :                       gcc_assert (!POINTER_TYPE_P (TREE_TYPE (decl)));
    4922          228 :                       tree tmp = TREE_OPERAND (decl, 0);
    4923          228 :                       tmp = gfc_build_cond_assign_expr (&iter_block,
    4924              :                                                         present, tmp,
    4925              :                                                         null_pointer_node);
    4926          228 :                       OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (tmp);
    4927              :                     }
    4928              :                   else
    4929         8223 :                     OMP_CLAUSE_DECL (node) = decl;
    4930              : 
    4931         9845 :                   if (!n->sym->attr.dimension
    4932         6148 :                       && n->sym->ts.type == BT_CHARACTER
    4933          144 :                       && n->sym->ts.deferred)
    4934              :                     {
    4935           48 :                       if (!DECL_P (decl))
    4936              :                         {
    4937           48 :                           gcc_assert (TREE_CODE (decl) == INDIRECT_REF);
    4938           48 :                           decl = TREE_OPERAND (decl, 0);
    4939              :                         }
    4940           48 :                       tree cond = fold_build2_loc (input_location, NE_EXPR,
    4941              :                                                    boolean_type_node,
    4942              :                                                    decl, null_pointer_node);
    4943           48 :                       if (present)
    4944            2 :                         cond = fold_build2_loc (input_location,
    4945              :                                                 TRUTH_ANDIF_EXPR,
    4946              :                                                 boolean_type_node,
    4947              :                                                 present, cond);
    4948           48 :                       tree len = n->sym->ts.u.cl->backend_decl;
    4949           48 :                       len = fold_convert (size_type_node, len);
    4950           48 :                       tree size = gfc_get_char_type (n->sym->ts.kind);
    4951           48 :                       size = TYPE_SIZE_UNIT (size);
    4952           48 :                       size = fold_build2 (MULT_EXPR, size_type_node, len, size);
    4953           48 :                       size = build3_loc (input_location,
    4954              :                                                          COND_EXPR,
    4955              :                                                          size_type_node,
    4956              :                                                          cond, size,
    4957              :                                                          size_zero_node);
    4958           48 :                       size = gfc_evaluate_now (size, &iter_block);
    4959           48 :                       OMP_CLAUSE_SIZE (node) = size;
    4960              :                     }
    4961         9845 :                   if ((TREE_CODE (decl) != PARM_DECL
    4962          186 :                        || DECL_ARTIFICIAL (OMP_CLAUSE_DECL (node)))
    4963         9659 :                       && n->sym->ts.type == BT_DERIVED
    4964        10389 :                       && n->sym->ts.u.derived->attr.alloc_comp)
    4965              :                     {
    4966              :                       /* Save array descriptor for use in
    4967              :                          gfc_omp_deep_mapping{,_p,_cnt}; force evaluate
    4968              :                          to ensure that it is not gimplified + is a decl.  */
    4969          212 :                       tree tmp = OMP_CLAUSE_SIZE (node);
    4970          212 :                       if (tmp == NULL_TREE)
    4971          229 :                         tmp = DECL_P (decl) ? DECL_SIZE_UNIT (decl)
    4972           46 :                                             : TYPE_SIZE_UNIT (TREE_TYPE (decl));
    4973          212 :                       tree var = gfc_create_var (TREE_TYPE (tmp), NULL);
    4974          212 :                       gfc_add_modify_loc (input_location, &iter_block,
    4975              :                                           var, tmp);
    4976          212 :                       OMP_CLAUSE_SIZE (node) = var;
    4977          212 :                       gfc_allocate_lang_decl (var);
    4978          212 :                       if (TREE_CODE (decl) == INDIRECT_REF)
    4979           48 :                         decl = TREE_OPERAND (decl, 0);
    4980          212 :                       if (TREE_CODE (decl) == INDIRECT_REF)
    4981            2 :                         decl = TREE_OPERAND (decl, 0);
    4982          212 :                       if (DECL_LANG_SPECIFIC (decl)
    4983          212 :                           && GFC_DECL_SAVED_DESCRIPTOR (decl))
    4984            6 :                         GFC_DECL_SAVED_DESCRIPTOR (var)
    4985            2 :                           = GFC_DECL_SAVED_DESCRIPTOR (decl);
    4986              :                       else
    4987          210 :                         GFC_DECL_SAVED_DESCRIPTOR (var) = decl;
    4988              :                     }
    4989              :                 }
    4990         5807 :               else if (n->expr
    4991         5807 :                        && n->expr->expr_type == EXPR_VARIABLE
    4992         5807 :                        && n->expr->ref->type == REF_ARRAY
    4993         3677 :                        && !n->expr->ref->next)
    4994              :                 {
    4995              :                   /* An array element or array section which is not part of a
    4996              :                      derived type, etc.  */
    4997         3389 :                   bool element = n->expr->ref->u.ar.type == AR_ELEMENT;
    4998         3389 :                   tree type = TREE_TYPE (decl);
    4999         3389 :                   gomp_map_kind k = GOMP_MAP_POINTER;
    5000         3389 :                   if (!openacc
    5001          538 :                       && !GFC_DESCRIPTOR_TYPE_P (type)
    5002         3842 :                       && !(POINTER_TYPE_P (type)
    5003          281 :                            && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (type))))
    5004              :                     k = GOMP_MAP_FIRSTPRIVATE_POINTER;
    5005         3389 :                   gfc_trans_omp_array_section (&iter_block, op, n, decl,
    5006         3389 :                                                element, !openacc, k,
    5007              :                                                node, node2, node3, node4,
    5008              :                                                iterator);
    5009         3389 :                 }
    5010         2418 :               else if (n->expr
    5011         2418 :                        && n->expr->expr_type == EXPR_VARIABLE
    5012         2418 :                        && (n->expr->ref->type == REF_COMPONENT
    5013              :                            || n->expr->ref->type == REF_ARRAY)
    5014         2418 :                        && lastref
    5015         2418 :                        && lastref->type == REF_COMPONENT
    5016          457 :                        && lastref->u.c.component->ts.type != BT_CLASS
    5017          433 :                        && lastref->u.c.component->ts.type != BT_DERIVED
    5018          340 :                        && !lastref->u.c.component->attr.dimension)
    5019              :                 {
    5020              :                   /* Derived type access with last component being a scalar.  */
    5021          340 :                   gfc_init_se (&se, NULL);
    5022              : 
    5023          340 :                   gfc_conv_expr (&se, n->expr);
    5024          340 :                   gfc_add_block_to_block (&iter_block, &se.pre);
    5025              :                   /* For BT_CHARACTER a pointer is returned.  */
    5026          340 :                   OMP_CLAUSE_DECL (node)
    5027          586 :                     = POINTER_TYPE_P (TREE_TYPE (se.expr))
    5028          340 :                       ? build_fold_indirect_ref (se.expr) : se.expr;
    5029          340 :                   gfc_add_block_to_block (&iter_block, &se.post);
    5030          340 :                   if (pointer || allocatable)
    5031              :                     {
    5032              :                       /* If it's a bare attach/detach clause, we just want
    5033              :                          to perform a single attach/detach operation, of the
    5034              :                          pointer itself, not of the pointed-to object.  */
    5035          161 :                       if (openacc
    5036           68 :                           && (n->u.map.op == OMP_MAP_ATTACH
    5037           50 :                               || n->u.map.op == OMP_MAP_DETACH))
    5038              :                         {
    5039           36 :                           OMP_CLAUSE_DECL (node)
    5040           36 :                             = build_fold_addr_expr (OMP_CLAUSE_DECL (node));
    5041           36 :                           OMP_CLAUSE_SIZE (node) = size_zero_node;
    5042           36 :                           goto finalize_map_clause;
    5043              :                         }
    5044              : 
    5045          125 :                       node2 = build_omp_clause (map_loc, OMP_CLAUSE_MAP);
    5046          125 :                       OMP_CLAUSE_SET_MAP_KIND (node2, GOMP_MAP_ATTACH_DETACH);
    5047          125 :                       OMP_CLAUSE_DECL (node2)
    5048          180 :                         = POINTER_TYPE_P (TREE_TYPE (se.expr))
    5049          125 :                           ? se.expr
    5050           55 :                           : gfc_build_addr_expr (NULL, se.expr);
    5051          125 :                       OMP_CLAUSE_SIZE (node2) = size_int (0);
    5052          125 :                       if (!openacc
    5053           93 :                           && n->expr->ts.type == BT_CHARACTER
    5054           54 :                           && n->expr->ts.deferred)
    5055              :                         {
    5056           54 :                           gcc_assert (se.string_length);
    5057           54 :                           tree tmp
    5058           54 :                             = gfc_get_char_type (n->expr->ts.kind);
    5059           54 :                           OMP_CLAUSE_SIZE (node)
    5060           54 :                             = fold_build2 (MULT_EXPR, size_type_node,
    5061              :                                            fold_convert (size_type_node,
    5062              :                                                se.string_length),
    5063              :                                            TYPE_SIZE_UNIT (tmp));
    5064           54 :                           gomp_map_kind kind;
    5065           54 :                           if (n->u.map.op == OMP_MAP_DELETE)
    5066              :                             kind = GOMP_MAP_DELETE;
    5067           54 :                           else if (op == EXEC_OMP_TARGET_EXIT_DATA)
    5068              :                             kind = GOMP_MAP_RELEASE;
    5069              :                           else
    5070           48 :                             kind = GOMP_MAP_TO;
    5071           54 :                           node3 = build_omp_clause (map_loc, OMP_CLAUSE_MAP);
    5072           54 :                           OMP_CLAUSE_SET_MAP_KIND (node3, kind);
    5073           54 :                           OMP_CLAUSE_DECL (node3) = se.string_length;
    5074           54 :                           OMP_CLAUSE_SIZE (node3)
    5075          108 :                             = TYPE_SIZE_UNIT (gfc_charlen_type_node);
    5076              :                         }
    5077           93 :                       if (!openacc
    5078           93 :                           && n->expr->ts.type == BT_DERIVED
    5079            0 :                           && n->expr->ts.u.derived->attr.alloc_comp)
    5080              :                         {
    5081              :                           /* Save array descriptor for use in
    5082              :                              gfc_omp_deep_mapping{,_p,_cnt}; force evaluate
    5083              :                              to ensure that it is not gimplified + is a decl.  */
    5084            0 :                           tree tmp = OMP_CLAUSE_SIZE (node);
    5085            0 :                           if (tmp == NULL_TREE)
    5086            0 :                             tmp = (DECL_P (se.expr)
    5087            0 :                                    ? DECL_SIZE_UNIT (se.expr)
    5088            0 :                                    : TYPE_SIZE_UNIT (TREE_TYPE (se.expr)));
    5089            0 :                           tree var = gfc_create_var (TREE_TYPE (tmp), NULL);
    5090            0 :                           gfc_add_modify_loc (input_location, &iter_block,
    5091              :                                               var, tmp);
    5092            0 :                           OMP_CLAUSE_SIZE (node) = var;
    5093            0 :                           gfc_allocate_lang_decl (var);
    5094            0 :                           if (TREE_CODE (se.expr) == INDIRECT_REF)
    5095            0 :                             se.expr = TREE_OPERAND (se.expr, 0);
    5096            0 :                           if (DECL_LANG_SPECIFIC (se.expr)
    5097            0 :                               && GFC_DECL_SAVED_DESCRIPTOR (se.expr))
    5098            0 :                             GFC_DECL_SAVED_DESCRIPTOR (var)
    5099            0 :                               = GFC_DECL_SAVED_DESCRIPTOR (se.expr);
    5100              :                           else
    5101            0 :                             GFC_DECL_SAVED_DESCRIPTOR (var) = se.expr;
    5102              :                         }
    5103              :                     }
    5104              :                 }
    5105         2078 :               else if (n->expr
    5106         2078 :                        && n->expr->expr_type == EXPR_VARIABLE
    5107         2078 :                        && (n->expr->ref->type == REF_COMPONENT
    5108              :                            || n->expr->ref->type == REF_ARRAY))
    5109              :                 {
    5110         2078 :                   gfc_init_se (&se, NULL);
    5111         2078 :                   se.expr = gfc_maybe_dereference_var (n->sym, decl);
    5112         2078 :                   vec<tree> mid_descr = vNULL;
    5113         2078 :                   vec<gfc_ref *> midref = vNULL;
    5114              : 
    5115         7543 :                   for (gfc_ref *ref = n->expr->ref; ref; ref = ref->next)
    5116              :                     {
    5117         5465 :                       if (ref->type == REF_COMPONENT)
    5118              :                         {
    5119         2739 :                           if (ref->u.c.sym->attr.extension)
    5120           91 :                             conv_parent_component_references (&se, ref);
    5121              : 
    5122         2739 :                           gfc_conv_component_ref (&se, ref);
    5123         2739 :                           if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr)))
    5124              :                             {
    5125         1999 :                               mid_descr.safe_push (se.expr);
    5126         1999 :                               midref.safe_push (ref);
    5127              :                             }
    5128              :                         }
    5129         2726 :                       else if (ref->type == REF_ARRAY)
    5130              :                         {
    5131         2726 :                           if (ref->u.ar.type == AR_ELEMENT && ref->next)
    5132          765 :                             gfc_conv_array_ref (&se, &ref->u.ar, n->expr,
    5133          765 :                                                 &n->expr->where);
    5134              :                           else
    5135         1961 :                             gcc_assert (!ref->next);
    5136              :                         }
    5137              :                       else
    5138            0 :                         sorry_at (gfc_get_location (&n->where),
    5139              :                                   "unhandled expression type");
    5140              :                     }
    5141              : 
    5142         2078 :                   tree inner = se.expr;
    5143              : 
    5144              :                   /* Last component is a derived type or class pointer.  */
    5145         2078 :                   if (lastref->type == REF_COMPONENT
    5146          117 :                       && (lastref->u.c.component->ts.type == BT_DERIVED
    5147           24 :                           || lastref->u.c.component->ts.type == BT_CLASS))
    5148              :                     {
    5149          117 :                       if (pointer || allocatable)
    5150              :                         {
    5151              :                           /* If it's a bare attach/detach clause, we just want
    5152              :                              to perform a single attach/detach operation, of the
    5153              :                              pointer itself, not of the pointed-to object.  */
    5154           67 :                           if (openacc
    5155           49 :                               && (n->u.map.op == OMP_MAP_ATTACH
    5156           43 :                                   || n->u.map.op == OMP_MAP_DETACH))
    5157              :                             {
    5158           12 :                               OMP_CLAUSE_DECL (node)
    5159           12 :                                 = build_fold_addr_expr (inner);
    5160           12 :                               OMP_CLAUSE_SIZE (node) = size_zero_node;
    5161           18 :                               goto finalize_map_clause;
    5162              :                             }
    5163              : 
    5164           18 :                           gfc_omp_namelist *n2
    5165              :                             = openacc ? NULL : clauses->lists[OMP_LIST_MAP];
    5166              : 
    5167           55 :                           bool sym_based;
    5168           55 :                           n2 = get_symbol_rooted_namelist (sym_rooted_nl, n,
    5169              :                                                            n2, &sym_based);
    5170              : 
    5171              :                           /* If the last reference is a pointer to a derived
    5172              :                              type ("foo%dt_ptr"), check if any subcomponents
    5173              :                              of the same derived type member are being mapped
    5174              :                              elsewhere in the clause list ("foo%dt_ptr%x",
    5175              :                              etc.).  If we have such subcomponent mappings,
    5176              :                              we only create an ALLOC node for the pointer
    5177              :                              itself, and inhibit mapping the whole derived
    5178              :                              type.  */
    5179              : 
    5180          103 :                           for (; n2 != NULL; n2 = n2->next)
    5181              :                             {
    5182           54 :                               if ((!sym_based && n == n2)
    5183           54 :                                   || (sym_based && n == n2->u2.duplicate_of)
    5184           42 :                                   || !n2->expr)
    5185           12 :                                 continue;
    5186              : 
    5187           42 :                               if (!gfc_omp_expr_prefix_same (n->expr,
    5188              :                                                              n2->expr))
    5189           36 :                                 continue;
    5190              : 
    5191            6 :                               gfc_ref *ref1 = n->expr->ref;
    5192            6 :                               gfc_ref *ref2 = n2->expr->ref;
    5193              : 
    5194            6 :                               while (ref1->next && ref2->next)
    5195              :                                 {
    5196              :                                   ref1 = ref1->next;
    5197              :                                   ref2 = ref2->next;
    5198              :                                 }
    5199              : 
    5200            6 :                               if (ref2->next)
    5201              :                                 {
    5202            6 :                                   inner = build_fold_addr_expr (inner);
    5203            6 :                                   OMP_CLAUSE_SET_MAP_KIND (node,
    5204              :                                                            GOMP_MAP_ALLOC);
    5205            6 :                                   OMP_CLAUSE_DECL (node) = inner;
    5206            6 :                                   OMP_CLAUSE_SIZE (node)
    5207            6 :                                     = TYPE_SIZE_UNIT (TREE_TYPE (inner));
    5208            6 :                                   goto finalize_map_clause;
    5209              :                                 }
    5210              :                             }
    5211              : 
    5212           49 :                           tree data, size;
    5213              : 
    5214           49 :                           if (lastref->u.c.component->ts.type == BT_CLASS)
    5215              :                             {
    5216           24 :                               data = gfc_class_data_get (inner);
    5217           24 :                               gcc_assert (POINTER_TYPE_P (TREE_TYPE (data)));
    5218           24 :                               data = build_fold_indirect_ref (data);
    5219           24 :                               size = gfc_class_vtab_size_get (inner);
    5220              :                             }
    5221              :                           else  /* BT_DERIVED.  */
    5222              :                             {
    5223           25 :                               data = inner;
    5224           25 :                               size = TYPE_SIZE_UNIT (TREE_TYPE (inner));
    5225              :                             }
    5226              : 
    5227           49 :                           OMP_CLAUSE_DECL (node) = data;
    5228           49 :                           OMP_CLAUSE_SIZE (node) = size;
    5229           49 :                           node2 = build_omp_clause (map_loc, OMP_CLAUSE_MAP);
    5230           49 :                           OMP_CLAUSE_SET_MAP_KIND (node2,
    5231              :                                                    GOMP_MAP_ATTACH_DETACH);
    5232           49 :                           OMP_CLAUSE_DECL (node2) = build_fold_addr_expr (data);
    5233           49 :                           OMP_CLAUSE_SIZE (node2) = size_int (0);
    5234              :                         }
    5235              :                       else
    5236              :                         {
    5237           50 :                           OMP_CLAUSE_DECL (node) = inner;
    5238           50 :                           OMP_CLAUSE_SIZE (node)
    5239          100 :                             = TYPE_SIZE_UNIT (TREE_TYPE (inner));
    5240              :                         }
    5241           99 :                       if (!openacc
    5242           15 :                           && n->expr->ts.type == BT_DERIVED
    5243           15 :                           && n->expr->ts.u.derived->attr.alloc_comp)
    5244              :                         {
    5245              :                           /* Save array descriptor for use in
    5246              :                              gfc_omp_deep_mapping{,_p,_cnt}; force evaluate
    5247              :                              to ensure that it is not gimplified + is a decl.  */
    5248            8 :                           tree tmp = OMP_CLAUSE_SIZE (node);
    5249            8 :                           tree var = gfc_create_var (TREE_TYPE (tmp), NULL);
    5250            8 :                           gfc_add_modify_loc (input_location, &iter_block,
    5251              :                                               var, tmp);
    5252            8 :                           OMP_CLAUSE_SIZE (node) = var;
    5253            8 :                           gfc_allocate_lang_decl (var);
    5254            8 :                           if (TREE_CODE (inner) == INDIRECT_REF)
    5255            6 :                             inner = TREE_OPERAND (inner, 0);
    5256            8 :                           GFC_DECL_SAVED_DESCRIPTOR (var) = inner;
    5257              :                         }
    5258              :                     }
    5259         1961 :                   else if (lastref->type == REF_ARRAY
    5260         1961 :                            && lastref->u.ar.type == AR_FULL)
    5261              :                     {
    5262              :                       /* Bare attach and detach clauses don't want any
    5263              :                          additional nodes.  */
    5264         1234 :                       if ((n->u.map.op == OMP_MAP_ATTACH
    5265         1203 :                            || n->u.map.op == OMP_MAP_DETACH)
    5266         1248 :                           && (POINTER_TYPE_P (TREE_TYPE (inner))
    5267           45 :                               || GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (inner))))
    5268              :                         {
    5269           45 :                           if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (inner)))
    5270              :                             {
    5271           45 :                               tree ptr = gfc_conv_descriptor_data_get (inner);
    5272           45 :                               OMP_CLAUSE_DECL (node) = ptr;
    5273              :                             }
    5274              :                           else
    5275            0 :                             OMP_CLAUSE_DECL (node) = inner;
    5276           45 :                           OMP_CLAUSE_SIZE (node) = size_zero_node;
    5277           45 :                           goto finalize_map_clause;
    5278              :                         }
    5279              : 
    5280         1189 :                       if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (inner)))
    5281              :                         {
    5282         1019 :                           bool drop_mapping = gfc_map_array_descriptor (
    5283              :                             node, node2, node3, node4, inner, openacc, map_loc,
    5284              :                             &iter_block, op, n, sym_rooted_nl, se, clauses,
    5285              :                             false);
    5286         1019 :                           if (drop_mapping)
    5287          286 :                             continue;
    5288              :                         }
    5289              :                       else
    5290          170 :                         OMP_CLAUSE_DECL (node) = inner;
    5291              :                     }
    5292          727 :                   else if (lastref->type == REF_ARRAY)
    5293              :                     {
    5294              :                       /* An array element or section.  */
    5295          727 :                       bool element = lastref->u.ar.type == AR_ELEMENT;
    5296          727 :                       gomp_map_kind kind = GOMP_MAP_ATTACH_DETACH;
    5297          727 :                       gfc_trans_omp_array_section (&iter_block, op, n, inner,
    5298          727 :                                                    element, !openacc, kind,
    5299              :                                                    node, node2, node3, node4,
    5300              :                                                    iterator);
    5301              :                     }
    5302              :                   else
    5303            0 :                     gcc_unreachable ();
    5304              : 
    5305              :                   /* Map intermediate array descriptors.  */
    5306         1645 :                   if (!openacc && !mid_descr.is_empty ())
    5307         2321 :                     for (size_t i = 0; i < mid_descr.length (); i++)
    5308         1333 :                       if (mid_descr[i] != inner
    5309         1333 :                           && !descriptors.contains (midref[i]->u.c.sym))
    5310              :                         {
    5311          172 :                           descriptors.safe_push (midref[i]->u.c.sym);
    5312          172 :                           tree node1 = copy_node (node);
    5313          172 :                           tree node2 = NULL_TREE;
    5314          172 :                           tree node3 = NULL_TREE;
    5315          172 :                           tree node4 = NULL_TREE;
    5316          344 :                           gfc_map_array_descriptor (node1, node2, node3, node4,
    5317          172 :                                                     mid_descr[i], openacc,
    5318              :                                                     map_loc, &iter_block,
    5319              :                                                     op, n,
    5320              :                                                     sym_rooted_nl, se, clauses,
    5321              :                                                     true);
    5322              : 
    5323          172 :                           if (node1 != NULL_TREE)
    5324           90 :                             omp_clauses
    5325           90 :                               = gfc_trans_add_clause (node1, omp_clauses);
    5326          172 :                           if (node2 != NULL_TREE)
    5327          172 :                             omp_clauses
    5328          172 :                               = gfc_trans_add_clause (node2, omp_clauses);
    5329          172 :                           if (node3 != NULL_TREE)
    5330          172 :                             omp_clauses
    5331          172 :                               = gfc_trans_add_clause (node3, omp_clauses);
    5332          172 :                           if (node4 != NULL_TREE)
    5333            0 :                             omp_clauses
    5334            0 :                               = gfc_trans_add_clause (node4, omp_clauses);
    5335              :                         }
    5336         1729 :                 }
    5337              :               else
    5338            0 :                 sorry_at (gfc_get_location (&n->where), "unhandled expression");
    5339              : 
    5340        15443 :               finalize_map_clause:
    5341              : 
    5342        15443 :               if (!iterator)
    5343        15404 :                 gfc_add_block_to_block (block, &iter_block);
    5344              : 
    5345        15443 :               omp_clauses = gfc_trans_add_clause (node, omp_clauses);
    5346        15443 :               if (node2)
    5347         5153 :                 omp_clauses = gfc_trans_add_clause (node2, omp_clauses);
    5348        15443 :               if (node3)
    5349         6422 :                 omp_clauses = gfc_trans_add_clause (node3, omp_clauses);
    5350        15443 :               if (node4)
    5351         3562 :                 omp_clauses = gfc_trans_add_clause (node4, omp_clauses);
    5352        15443 :               if (node5)
    5353            4 :                 omp_clauses = gfc_trans_add_clause (node5, omp_clauses);
    5354              :             }
    5355         9196 :           if (iterator)
    5356           12 :             finish_iterator_group (list, &iter_block, tree_block,
    5357              :                                    iterator, omp_clauses, prev_clauses);
    5358              :           break;
    5359              :         case OMP_LIST_TO:
    5360              :         case OMP_LIST_FROM:
    5361              :         case OMP_LIST_CACHE:
    5362              :           iterator = NULL_TREE;
    5363              :           prev = NULL;
    5364              :           prev_clauses = omp_clauses;
    5365         3662 :           for (; n != NULL; n = n->next)
    5366              :             {
    5367         1876 :               if (!n->sym->attr.referenced
    5368            0 :                   && n->sym->attr.flavor != FL_PARAMETER)
    5369            0 :                 continue;
    5370              : 
    5371         1876 :               if (iterator && prev->u2.ns != n->u2.ns)
    5372              :                 {
    5373            0 :                   finish_iterator_group (list, &iter_block, tree_block,
    5374              :                                          iterator, omp_clauses, prev_clauses);
    5375            0 :                   prev_clauses = omp_clauses;
    5376            0 :                   iterator = NULL_TREE;
    5377              :                 }
    5378         1876 :               if (n->u2.ns && (!prev || prev->u2.ns != n->u2.ns))
    5379              :                 {
    5380              :                   /* Start a new iterator group.  */
    5381           11 :                   iterator = start_iterator_group (n->u2.ns, block,
    5382              :                                                    &iter_block, tree_block);
    5383           11 :                   prev_clauses = omp_clauses;
    5384              :                 }
    5385         1876 :               if (!iterator)
    5386         1862 :                 gfc_init_block (&iter_block);
    5387         1876 :               prev = n;
    5388              : 
    5389         1876 :               switch (list)
    5390              :                 {
    5391              :                 case OMP_LIST_TO:
    5392              :                   clause_code = OMP_CLAUSE_TO;
    5393              :                   break;
    5394         1032 :                 case OMP_LIST_FROM:
    5395         1032 :                   clause_code = OMP_CLAUSE_FROM;
    5396         1032 :                   break;
    5397           84 :                 case OMP_LIST_CACHE:
    5398           84 :                   clause_code = OMP_CLAUSE__CACHE_;
    5399           84 :                   break;
    5400            0 :                 default:
    5401            0 :                   gcc_unreachable ();
    5402              :                 }
    5403         1876 :               tree node = build_omp_clause (gfc_get_location (&n->where),
    5404              :                                             clause_code);
    5405         1876 :               if (n->expr == NULL
    5406          141 :                   || (n->expr->ref->type == REF_ARRAY
    5407          129 :                       && n->expr->ref->u.ar.type == AR_FULL
    5408            0 :                       && n->expr->ref->next == NULL))
    5409              :                 {
    5410         1735 :                   tree decl = gfc_trans_omp_variable (n->sym, false);
    5411         1735 :                   if (gfc_omp_privatize_by_reference (decl))
    5412              :                     {
    5413         1047 :                       if (gfc_omp_is_allocatable_or_ptr (decl))
    5414          240 :                         decl = build_fold_indirect_ref (decl);
    5415         1047 :                       decl = build_fold_indirect_ref (decl);
    5416              :                     }
    5417          688 :                   else if (DECL_P (decl))
    5418          688 :                     TREE_ADDRESSABLE (decl) = 1;
    5419         1735 :                   if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
    5420              :                     {
    5421          597 :                       tree type = TREE_TYPE (decl);
    5422          597 :                       tree ptr = gfc_conv_descriptor_data_get (decl);
    5423          597 :                       gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
    5424          597 :                       ptr = build_fold_indirect_ref (ptr);
    5425          597 :                       OMP_CLAUSE_DECL (node) = ptr;
    5426          597 :                       OMP_CLAUSE_SIZE (node)
    5427          597 :                         = gfc_full_array_size (&iter_block, decl,
    5428          597 :                                                GFC_TYPE_ARRAY_RANK (type));
    5429          597 :                       tree elemsz
    5430          597 :                         = TYPE_SIZE_UNIT (gfc_get_element_type (type));
    5431          597 :                       elemsz = fold_convert (gfc_array_index_type, elemsz);
    5432         1194 :                       OMP_CLAUSE_SIZE (node)
    5433         1194 :                         = fold_build2 (MULT_EXPR, gfc_array_index_type,
    5434              :                                        OMP_CLAUSE_SIZE (node), elemsz);
    5435              :                     }
    5436              :                   else
    5437              :                     {
    5438         1138 :                       OMP_CLAUSE_DECL (node) = decl;
    5439         1138 :                       if (gfc_omp_is_allocatable_or_ptr (decl))
    5440          120 :                         OMP_CLAUSE_SIZE (node)
    5441          240 :                                 = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl)));
    5442              :                     }
    5443              :                 }
    5444              :               else
    5445              :                 {
    5446          141 :                   tree ptr;
    5447          141 :                   gfc_init_se (&se, NULL);
    5448          141 :                   if (n->expr->rank == 0)
    5449              :                     {
    5450            9 :                       gfc_conv_expr_reference (&se, n->expr);
    5451            9 :                       ptr = se.expr;
    5452            9 :                       gfc_add_block_to_block (&iter_block, &se.pre);
    5453            9 :                       OMP_CLAUSE_SIZE (node)
    5454           18 :                         = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ptr)));
    5455              :                     }
    5456              :                   else
    5457              :                     {
    5458          132 :                       gfc_conv_expr_descriptor (&se, n->expr);
    5459          132 :                       ptr = gfc_conv_array_data (se.expr);
    5460          132 :                       tree type = TREE_TYPE (se.expr);
    5461          132 :                       gfc_add_block_to_block (&iter_block, &se.pre);
    5462          132 :                       OMP_CLAUSE_SIZE (node)
    5463          132 :                         = gfc_full_array_size (&iter_block, se.expr,
    5464          132 :                                                GFC_TYPE_ARRAY_RANK (type));
    5465          132 :                       tree elemsz
    5466          132 :                         = TYPE_SIZE_UNIT (gfc_get_element_type (type));
    5467          132 :                       elemsz = fold_convert (gfc_array_index_type, elemsz);
    5468          264 :                       OMP_CLAUSE_SIZE (node)
    5469          264 :                         = fold_build2 (MULT_EXPR, gfc_array_index_type,
    5470              :                                        OMP_CLAUSE_SIZE (node), elemsz);
    5471              :                     }
    5472          141 :                   gfc_add_block_to_block (&iter_block, &se.post);
    5473          141 :                   gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
    5474          141 :                   OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr);
    5475              :                 }
    5476         1876 :               if (n->u.present_modifier)
    5477            5 :                 OMP_CLAUSE_MOTION_PRESENT (node) = 1;
    5478         1876 :               if (list == OMP_LIST_CACHE && n->u.map.readonly)
    5479           16 :                 OMP_CLAUSE__CACHE__READONLY (node) = 1;
    5480         1876 :               if (!iterator)
    5481         1862 :                 gfc_add_block_to_block (block, &iter_block);
    5482         1876 :               omp_clauses = gfc_trans_add_clause (node, omp_clauses);
    5483              :             }
    5484         1786 :           if (iterator)
    5485           11 :             finish_iterator_group (list, &iter_block, tree_block,
    5486              :                                    iterator, omp_clauses, prev_clauses);
    5487              :           break;
    5488              :         case OMP_LIST_USES_ALLOCATORS:
    5489           90 :           for (; n != NULL; n = n->next)
    5490              :             {
    5491           61 :               if (!n->sym->attr.referenced)
    5492           43 :                 continue;
    5493           18 :               tree node = build_omp_clause (input_location,
    5494              :                                             OMP_CLAUSE_USES_ALLOCATORS);
    5495           18 :               tree t;
    5496           18 :               if (n->sym->attr.flavor == FL_VARIABLE)
    5497           16 :                 t = gfc_get_symbol_decl (n->sym);
    5498              :               else
    5499              :                 {
    5500            2 :                   t = gfc_conv_mpz_to_tree (n->sym->value->value.integer,
    5501              :                                             n->sym->ts.kind);
    5502            2 :                   t = fold_convert (ptr_type_node, t);
    5503              :                 }
    5504           18 :               OMP_CLAUSE_USES_ALLOCATORS_ALLOCATOR(node) = t;
    5505           18 :               if (n->u.memspace_sym)
    5506              :                 {
    5507            5 :                   gcc_checking_assert (n->u.memspace_sym->attr.flavor
    5508              :                                        == FL_PARAMETER
    5509              :                                        && !n->u.memspace_sym->attr.dimension);
    5510            5 :                   n->u.memspace_sym->attr.referenced = true;
    5511            5 :                   gfc_init_se (&se, NULL);
    5512            5 :                   gfc_conv_expr (&se, n->u.memspace_sym->value);
    5513            5 :                   OMP_CLAUSE_USES_ALLOCATORS_MEMSPACE (node) = se.expr;
    5514              :                 }
    5515           18 :               if (n->u2.traits_sym)
    5516              :                 {
    5517            9 :                   n->u2.traits_sym->attr.referenced = true;
    5518            9 :                   OMP_CLAUSE_USES_ALLOCATORS_TRAITS (node)
    5519           18 :                     = gfc_get_symbol_decl (n->u2.traits_sym);
    5520              :                 }
    5521           18 :               omp_clauses = gfc_trans_add_clause (node, omp_clauses);
    5522              :             }
    5523              :           break;
    5524              :         default:
    5525              :           break;
    5526              :         }
    5527              :     }
    5528              : 
    5529              :   /* Free hashmap if we built it.  */
    5530        32220 :   if (sym_rooted_nl)
    5531              :     {
    5532          388 :       typedef hash_map<gfc_symbol *, gfc_omp_namelist *>::iterator hti;
    5533         1278 :       for (hti it = sym_rooted_nl->begin (); it != sym_rooted_nl->end (); ++it)
    5534              :         {
    5535          445 :           gfc_omp_namelist *&nl = (*it).second;
    5536         1771 :           while (nl)
    5537              :             {
    5538         1326 :               gfc_omp_namelist *next = nl->next;
    5539         1326 :               free (nl);
    5540         1326 :               nl = next;
    5541              :             }
    5542              :         }
    5543          388 :       delete sym_rooted_nl;
    5544              :     }
    5545              : 
    5546        32220 :   if (clauses->if_expr)
    5547              :     {
    5548         1118 :       tree if_var;
    5549              : 
    5550         1118 :       gfc_init_se (&se, NULL);
    5551         1118 :       gfc_conv_expr (&se, clauses->if_expr);
    5552         1118 :       gfc_add_block_to_block (block, &se.pre);
    5553         1118 :       if_var = gfc_evaluate_now (se.expr, block);
    5554         1118 :       gfc_add_block_to_block (block, &se.post);
    5555              : 
    5556         1118 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_IF);
    5557         1118 :       OMP_CLAUSE_IF_MODIFIER (c) = ERROR_MARK;
    5558         1118 :       OMP_CLAUSE_IF_EXPR (c) = if_var;
    5559         1118 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    5560              :     }
    5561              : 
    5562       354420 :   for (ifc = 0; ifc < OMP_IF_LAST; ifc++)
    5563       322200 :     if (clauses->if_exprs[ifc])
    5564              :       {
    5565          123 :         tree if_var;
    5566              : 
    5567          123 :         gfc_init_se (&se, NULL);
    5568          123 :         gfc_conv_expr (&se, clauses->if_exprs[ifc]);
    5569          123 :         gfc_add_block_to_block (block, &se.pre);
    5570          123 :         if_var = gfc_evaluate_now (se.expr, block);
    5571          123 :         gfc_add_block_to_block (block, &se.post);
    5572              : 
    5573          123 :         c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_IF);
    5574          123 :         switch (ifc)
    5575              :           {
    5576            0 :           case OMP_IF_CANCEL:
    5577            0 :             OMP_CLAUSE_IF_MODIFIER (c) = VOID_CST;
    5578            0 :             break;
    5579           40 :           case OMP_IF_PARALLEL:
    5580           40 :             OMP_CLAUSE_IF_MODIFIER (c) = OMP_PARALLEL;
    5581           40 :             break;
    5582           39 :           case OMP_IF_SIMD:
    5583           39 :             OMP_CLAUSE_IF_MODIFIER (c) = OMP_SIMD;
    5584           39 :             break;
    5585            1 :           case OMP_IF_TASK:
    5586            1 :             OMP_CLAUSE_IF_MODIFIER (c) = OMP_TASK;
    5587            1 :             break;
    5588           23 :           case OMP_IF_TASKLOOP:
    5589           23 :             OMP_CLAUSE_IF_MODIFIER (c) = OMP_TASKLOOP;
    5590           23 :             break;
    5591           16 :           case OMP_IF_TARGET:
    5592           16 :             OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET;
    5593           16 :             break;
    5594            1 :           case OMP_IF_TARGET_DATA:
    5595            1 :             OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET_DATA;
    5596            1 :             break;
    5597            1 :           case OMP_IF_TARGET_UPDATE:
    5598            1 :             OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET_UPDATE;
    5599            1 :             break;
    5600            1 :           case OMP_IF_TARGET_ENTER_DATA:
    5601            1 :             OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET_ENTER_DATA;
    5602            1 :             break;
    5603            1 :           case OMP_IF_TARGET_EXIT_DATA:
    5604            1 :             OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET_EXIT_DATA;
    5605            1 :             break;
    5606              :           default:
    5607              :             gcc_unreachable ();
    5608              :           }
    5609          123 :         OMP_CLAUSE_IF_EXPR (c) = if_var;
    5610          123 :         omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    5611              :       }
    5612              : 
    5613        32220 :   if (clauses->self_expr)
    5614              :     {
    5615          159 :       tree self_var;
    5616              : 
    5617          159 :       gfc_init_se (&se, NULL);
    5618          159 :       gfc_conv_expr (&se, clauses->self_expr);
    5619          159 :       gfc_add_block_to_block (block, &se.pre);
    5620          159 :       self_var = gfc_evaluate_now (se.expr, block);
    5621          159 :       gfc_add_block_to_block (block, &se.post);
    5622              : 
    5623          159 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SELF);
    5624          159 :       OMP_CLAUSE_SELF_EXPR (c) = self_var;
    5625          159 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    5626              :     }
    5627              : 
    5628        32220 :   if (clauses->final_expr)
    5629              :     {
    5630           64 :       tree final_var;
    5631              : 
    5632           64 :       gfc_init_se (&se, NULL);
    5633           64 :       gfc_conv_expr (&se, clauses->final_expr);
    5634           64 :       gfc_add_block_to_block (block, &se.pre);
    5635           64 :       final_var = gfc_evaluate_now (se.expr, block);
    5636           64 :       gfc_add_block_to_block (block, &se.post);
    5637              : 
    5638           64 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_FINAL);
    5639           64 :       OMP_CLAUSE_FINAL_EXPR (c) = final_var;
    5640           64 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    5641              :     }
    5642              : 
    5643        32220 :   if (clauses->message || clauses->severity != OMP_SEVERITY_UNSET)
    5644              :     {
    5645           19 :       tree message = NULL_TREE;
    5646           19 :       tree len = NULL_TREE;
    5647              : 
    5648           19 :       if (clauses->message)
    5649              :         {
    5650           17 :           gfc_init_se (&se, NULL);
    5651           17 :           gfc_conv_expr (&se, clauses->message);
    5652           17 :           gfc_add_block_to_block (block, &se.pre);
    5653           17 :           message = se.expr;
    5654           17 :           len = se.string_length;
    5655           17 :           if (!DECL_P (se.expr))
    5656           17 :             message = gfc_evaluate_now (message, block);
    5657           17 :           gfc_add_block_to_block (block, &se.post);
    5658              : 
    5659           17 :           if (!POINTER_TYPE_P (TREE_TYPE (message)))
    5660              :             /* To ensure an ARRAY_TYPE is not passed as such.  */
    5661           17 :             message = gfc_build_addr_expr (NULL, message);
    5662              :         }
    5663              : 
    5664           19 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_MESSAGE);
    5665           19 :       OMP_CLAUSE_MESSAGE_EXPR (c) = message;
    5666           19 :       OMP_CLAUSE_MESSAGE_LEN (c) = len;
    5667           19 :       if (clauses->severity == OMP_SEVERITY_WARNING)
    5668           10 :         OMP_CLAUSE_MESSAGE_SEVERITY_WARN (c) = 1;
    5669           19 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    5670              :     }
    5671              : 
    5672        32220 :   if (clauses->novariants)
    5673              :     {
    5674            8 :       tree novariants_var;
    5675              : 
    5676            8 :       gfc_init_se (&se, NULL);
    5677            8 :       gfc_conv_expr (&se, clauses->novariants);
    5678            8 :       gfc_add_block_to_block (block, &se.pre);
    5679            8 :       novariants_var = gfc_evaluate_now (se.expr, block);
    5680            8 :       gfc_add_block_to_block (block, &se.post);
    5681              : 
    5682            8 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NOVARIANTS);
    5683            8 :       OMP_CLAUSE_NOVARIANTS_EXPR (c) = novariants_var;
    5684            8 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    5685              :     }
    5686              : 
    5687        32220 :   if (clauses->nocontext)
    5688              :     {
    5689            9 :       tree nocontext_var;
    5690              : 
    5691            9 :       gfc_init_se (&se, NULL);
    5692            9 :       gfc_conv_expr (&se, clauses->nocontext);
    5693            9 :       gfc_add_block_to_block (block, &se.pre);
    5694            9 :       nocontext_var = gfc_evaluate_now (se.expr, block);
    5695            9 :       gfc_add_block_to_block (block, &se.post);
    5696              : 
    5697            9 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NOCONTEXT);
    5698            9 :       OMP_CLAUSE_NOCONTEXT_EXPR (c) = nocontext_var;
    5699            9 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    5700              :     }
    5701              : 
    5702        32220 :   if (clauses->num_threads_list)
    5703              :     {
    5704              :       tree num_threads = NULL_TREE;
    5705         1987 :       for (gfc_expr_list *el = clauses->num_threads_list; el; el = el->next)
    5706         1006 :         num_threads = tree_cons (NULL_TREE,
    5707         1006 :                                  gfc_convert_expr_to_tree (block, el->expr),
    5708              :                                  num_threads);
    5709          981 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_THREADS);
    5710          981 :       OMP_CLAUSE_NUM_THREADS_EXPR (c) = nreverse (num_threads);
    5711          981 :       OMP_CLAUSE_NUM_THREADS_STRICT (c) = clauses->num_threads_strict;
    5712          981 :       OMP_CLAUSE_NUM_THREADS_DIMS (c) = clauses->num_threads_dims;
    5713          981 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    5714              :     }
    5715              : 
    5716        32220 :   if (clauses->device_type != OMP_DEVICE_TYPE_UNSET)
    5717              :     {
    5718            3 :       enum omp_clause_device_type_kind type;
    5719            3 :       switch (clauses->device_type)
    5720              :         {
    5721              :         case OMP_DEVICE_TYPE_HOST:
    5722              :           type = OMP_CLAUSE_DEVICE_TYPE_HOST;
    5723              :           break;
    5724              :         case OMP_DEVICE_TYPE_NOHOST:
    5725              :           type = OMP_CLAUSE_DEVICE_TYPE_NOHOST;
    5726              :           break;
    5727              :         case OMP_DEVICE_TYPE_ANY:
    5728              :           type = OMP_CLAUSE_DEVICE_TYPE_ANY;
    5729              :           break;
    5730            0 :         case OMP_DEVICE_TYPE_UNSET:
    5731            0 :         default:
    5732            0 :           gcc_unreachable ();
    5733              :         }
    5734            3 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DEVICE_TYPE);
    5735            3 :       OMP_CLAUSE_DEVICE_TYPE_KIND (c) = type;
    5736            3 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    5737              :     }
    5738              : 
    5739        32220 :   if (clauses->dyn_groupprivate)
    5740              :     {
    5741            5 :       gfc_init_se (&se, NULL);
    5742            5 :       gfc_conv_expr (&se, clauses->dyn_groupprivate);
    5743            5 :       gfc_add_block_to_block (block, &se.pre);
    5744            5 :       tree expr = (CONSTANT_CLASS_P (se.expr) || DECL_P (se.expr)
    5745            5 :                    ? se.expr : gfc_evaluate_now (se.expr, block));
    5746            5 :       gfc_add_block_to_block (block, &se.post);
    5747              : 
    5748            5 :       enum omp_clause_fallback_kind kind = OMP_CLAUSE_FALLBACK_UNSPECIFIED;
    5749            5 :       switch (clauses->fallback)
    5750              :         {
    5751              :         case OMP_FALLBACK_ABORT:
    5752              :           kind = OMP_CLAUSE_FALLBACK_ABORT;
    5753              :           break;
    5754              :         case OMP_FALLBACK_DEFAULT_MEM:
    5755              :           kind = OMP_CLAUSE_FALLBACK_DEFAULT_MEM;
    5756              :           break;
    5757              :         case OMP_FALLBACK_NULL:
    5758              :           kind = OMP_CLAUSE_FALLBACK_NULL;
    5759              :           break;
    5760              :         case OMP_FALLBACK_NONE:
    5761              :           break;
    5762              :         }
    5763            5 :       c = build_omp_clause (gfc_get_location (&where),
    5764              :                             OMP_CLAUSE_DYN_GROUPPRIVATE);
    5765            5 :       OMP_CLAUSE_DYN_GROUPPRIVATE_KIND (c) = kind;
    5766            5 :       OMP_CLAUSE_DYN_GROUPPRIVATE_EXPR (c) = expr;
    5767            5 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    5768              :     }
    5769              : 
    5770        32220 :   chunk_size = NULL_TREE;
    5771        32220 :   if (clauses->chunk_size)
    5772              :     {
    5773          493 :       gfc_init_se (&se, NULL);
    5774          493 :       gfc_conv_expr (&se, clauses->chunk_size);
    5775          493 :       gfc_add_block_to_block (block, &se.pre);
    5776          493 :       chunk_size = gfc_evaluate_now (se.expr, block);
    5777          493 :       gfc_add_block_to_block (block, &se.post);
    5778              :     }
    5779              : 
    5780        32220 :   if (clauses->sched_kind != OMP_SCHED_NONE)
    5781              :     {
    5782          782 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SCHEDULE);
    5783          782 :       OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = chunk_size;
    5784          782 :       switch (clauses->sched_kind)
    5785              :         {
    5786          407 :         case OMP_SCHED_STATIC:
    5787          407 :           OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC;
    5788          407 :           break;
    5789          159 :         case OMP_SCHED_DYNAMIC:
    5790          159 :           OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_DYNAMIC;
    5791          159 :           break;
    5792          125 :         case OMP_SCHED_GUIDED:
    5793          125 :           OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_GUIDED;
    5794          125 :           break;
    5795           84 :         case OMP_SCHED_RUNTIME:
    5796           84 :           OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_RUNTIME;
    5797           84 :           break;
    5798            7 :         case OMP_SCHED_AUTO:
    5799            7 :           OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_AUTO;
    5800            7 :           break;
    5801            0 :         default:
    5802            0 :           gcc_unreachable ();
    5803              :         }
    5804          782 :       if (clauses->sched_monotonic)
    5805           54 :         OMP_CLAUSE_SCHEDULE_KIND (c)
    5806           27 :           = (omp_clause_schedule_kind) (OMP_CLAUSE_SCHEDULE_KIND (c)
    5807              :                                         | OMP_CLAUSE_SCHEDULE_MONOTONIC);
    5808          755 :       else if (clauses->sched_nonmonotonic)
    5809           46 :         OMP_CLAUSE_SCHEDULE_KIND (c)
    5810           23 :           = (omp_clause_schedule_kind) (OMP_CLAUSE_SCHEDULE_KIND (c)
    5811              :                                         | OMP_CLAUSE_SCHEDULE_NONMONOTONIC);
    5812          782 :       if (clauses->sched_simd)
    5813           17 :         OMP_CLAUSE_SCHEDULE_SIMD (c) = 1;
    5814          782 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    5815              :     }
    5816              : 
    5817        32220 :   if (clauses->default_sharing != OMP_DEFAULT_UNKNOWN)
    5818              :     {
    5819         1087 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DEFAULT);
    5820         1087 :       switch (clauses->default_sharing)
    5821              :         {
    5822          677 :         case OMP_DEFAULT_NONE:
    5823          677 :           OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_NONE;
    5824          677 :           break;
    5825          183 :         case OMP_DEFAULT_SHARED:
    5826          183 :           OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_SHARED;
    5827          183 :           break;
    5828           24 :         case OMP_DEFAULT_PRIVATE:
    5829           24 :           OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_PRIVATE;
    5830           24 :           break;
    5831            8 :         case OMP_DEFAULT_FIRSTPRIVATE:
    5832            8 :           OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
    5833            8 :           break;
    5834          195 :         case OMP_DEFAULT_PRESENT:
    5835          195 :           OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_PRESENT;
    5836          195 :           break;
    5837            0 :         default:
    5838            0 :           gcc_unreachable ();
    5839              :         }
    5840         1087 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    5841              :     }
    5842              : 
    5843        32220 :   if (clauses->nowait)
    5844              :     {
    5845         2078 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NOWAIT);
    5846         2078 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    5847              :     }
    5848              : 
    5849        32220 :   if (clauses->full)
    5850              :     {
    5851           47 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_FULL);
    5852           47 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    5853              :     }
    5854              : 
    5855        32220 :   if (clauses->partial)
    5856              :     {
    5857          259 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_PARTIAL);
    5858          259 :       OMP_CLAUSE_PARTIAL_EXPR (c)
    5859          518 :         = (clauses->partial > 0
    5860          259 :            ? build_int_cst (integer_type_node, clauses->partial)
    5861              :            : NULL_TREE);
    5862          259 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    5863              :     }
    5864              : 
    5865        32220 :   if (clauses->sizes_list)
    5866              :     {
    5867              :       tree list = NULL_TREE;
    5868          344 :       for (gfc_expr_list *el = clauses->sizes_list; el; el = el->next)
    5869          224 :         list = tree_cons (NULL_TREE, gfc_convert_expr_to_tree (block, el->expr),
    5870              :                           list);
    5871              : 
    5872          120 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SIZES);
    5873          120 :       OMP_CLAUSE_SIZES_LIST (c) = nreverse (list);
    5874          120 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    5875              :     }
    5876              : 
    5877        32220 :   if (clauses->ordered)
    5878              :     {
    5879          315 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_ORDERED);
    5880          315 :       OMP_CLAUSE_ORDERED_EXPR (c)
    5881          315 :         = clauses->orderedc ? build_int_cst (integer_type_node,
    5882          134 :                                              clauses->orderedc) : NULL_TREE;
    5883          315 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    5884              :     }
    5885              : 
    5886        32220 :   if (clauses->order_concurrent)
    5887              :     {
    5888          303 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_ORDER);
    5889          303 :       OMP_CLAUSE_ORDER_UNCONSTRAINED (c) = clauses->order_unconstrained;
    5890          303 :       OMP_CLAUSE_ORDER_REPRODUCIBLE (c) = clauses->order_reproducible;
    5891          303 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    5892              :     }
    5893              : 
    5894        32220 :   if (clauses->untied)
    5895              :     {
    5896          141 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_UNTIED);
    5897          141 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    5898              :     }
    5899              : 
    5900        32220 :   if (clauses->mergeable)
    5901              :     {
    5902           32 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_MERGEABLE);
    5903           32 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    5904              :     }
    5905              : 
    5906        32220 :   if (clauses->collapse)
    5907              :     {
    5908         1646 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_COLLAPSE);
    5909         1646 :       OMP_CLAUSE_COLLAPSE_EXPR (c)
    5910         1646 :         = build_int_cst (integer_type_node, clauses->collapse);
    5911         1646 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    5912              :     }
    5913              : 
    5914        32220 :   if (clauses->inbranch)
    5915              :     {
    5916           18 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_INBRANCH);
    5917           18 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    5918              :     }
    5919              : 
    5920        32220 :   if (clauses->notinbranch)
    5921              :     {
    5922           23 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NOTINBRANCH);
    5923           23 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    5924              :     }
    5925              : 
    5926        32220 :   switch (clauses->cancel)
    5927              :     {
    5928              :     case OMP_CANCEL_UNKNOWN:
    5929              :       break;
    5930            0 :     case OMP_CANCEL_PARALLEL:
    5931            0 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_PARALLEL);
    5932            0 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    5933            0 :       break;
    5934            0 :     case OMP_CANCEL_SECTIONS:
    5935            0 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SECTIONS);
    5936            0 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    5937            0 :       break;
    5938            0 :     case OMP_CANCEL_DO:
    5939            0 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_FOR);
    5940            0 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    5941            0 :       break;
    5942            0 :     case OMP_CANCEL_TASKGROUP:
    5943            0 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_TASKGROUP);
    5944            0 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    5945            0 :       break;
    5946              :     }
    5947              : 
    5948        32220 :   if (clauses->proc_bind != OMP_PROC_BIND_UNKNOWN)
    5949              :     {
    5950           64 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_PROC_BIND);
    5951           64 :       switch (clauses->proc_bind)
    5952              :         {
    5953            1 :         case OMP_PROC_BIND_PRIMARY:
    5954            1 :           OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_PRIMARY;
    5955            1 :           break;
    5956            9 :         case OMP_PROC_BIND_MASTER:
    5957            9 :           OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_MASTER;
    5958            9 :           break;
    5959           53 :         case OMP_PROC_BIND_SPREAD:
    5960           53 :           OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_SPREAD;
    5961           53 :           break;
    5962            1 :         case OMP_PROC_BIND_CLOSE:
    5963            1 :           OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_CLOSE;
    5964            1 :           break;
    5965            0 :         default:
    5966            0 :           gcc_unreachable ();
    5967              :         }
    5968           64 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    5969              :     }
    5970              : 
    5971        32220 :   if (clauses->safelen_expr)
    5972              :     {
    5973           89 :       tree safelen_var;
    5974              : 
    5975           89 :       gfc_init_se (&se, NULL);
    5976           89 :       gfc_conv_expr (&se, clauses->safelen_expr);
    5977           89 :       gfc_add_block_to_block (block, &se.pre);
    5978           89 :       safelen_var = gfc_evaluate_now (se.expr, block);
    5979           89 :       gfc_add_block_to_block (block, &se.post);
    5980              : 
    5981           89 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SAFELEN);
    5982           89 :       OMP_CLAUSE_SAFELEN_EXPR (c) = safelen_var;
    5983           89 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    5984              :     }
    5985              : 
    5986        32220 :   if (clauses->simdlen_expr)
    5987              :     {
    5988          110 :       if (declare_simd)
    5989              :         {
    5990           65 :           c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SIMDLEN);
    5991           65 :           OMP_CLAUSE_SIMDLEN_EXPR (c)
    5992           65 :             = gfc_conv_constant_to_tree (clauses->simdlen_expr);
    5993           65 :           omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    5994              :         }
    5995              :       else
    5996              :         {
    5997           45 :           tree simdlen_var;
    5998              : 
    5999           45 :           gfc_init_se (&se, NULL);
    6000           45 :           gfc_conv_expr (&se, clauses->simdlen_expr);
    6001           45 :           gfc_add_block_to_block (block, &se.pre);
    6002           45 :           simdlen_var = gfc_evaluate_now (se.expr, block);
    6003           45 :           gfc_add_block_to_block (block, &se.post);
    6004              : 
    6005           45 :           c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SIMDLEN);
    6006           45 :           OMP_CLAUSE_SIMDLEN_EXPR (c) = simdlen_var;
    6007           45 :           omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    6008              :         }
    6009              :     }
    6010              : 
    6011        32220 :   if (clauses->num_teams_list)
    6012              :     {
    6013              :       tree num_teams = NULL_TREE;
    6014          313 :       for (gfc_expr_list *el = clauses->num_teams_list; el; el = el->next)
    6015          177 :         num_teams = tree_cons (NULL_TREE,
    6016          177 :                                gfc_convert_expr_to_tree (block, el->expr),
    6017              :                                num_teams);
    6018          136 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_TEAMS);
    6019          136 :       OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c) = NULL_TREE;
    6020          136 :       OMP_CLAUSE_NUM_TEAMS_UPPER_EXPR (c) = nreverse (num_teams);
    6021          136 :       OMP_CLAUSE_NUM_TEAMS_DIMS (c) = clauses->num_teams_dims;
    6022          136 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    6023              :     }
    6024              : 
    6025        32220 :   if (clauses->device)
    6026              :     {
    6027          297 :       tree device;
    6028              : 
    6029          297 :       gfc_init_se (&se, NULL);
    6030          297 :       gfc_conv_expr (&se, clauses->device);
    6031          297 :       gfc_add_block_to_block (block, &se.pre);
    6032          297 :       device = gfc_evaluate_now (se.expr, block);
    6033          297 :       gfc_add_block_to_block (block, &se.post);
    6034              : 
    6035          297 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DEVICE);
    6036          297 :       OMP_CLAUSE_DEVICE_ID (c) = device;
    6037              : 
    6038          297 :       if (clauses->ancestor)
    6039           39 :         OMP_CLAUSE_DEVICE_ANCESTOR (c) = 1;
    6040              : 
    6041          297 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    6042              :     }
    6043              : 
    6044        32220 :   if (clauses->thread_limit_list)
    6045              :     {
    6046              :       tree thread_limit = NULL_TREE;
    6047          304 :       for (gfc_expr_list *el = clauses->thread_limit_list; el; el = el->next)
    6048          163 :         thread_limit = tree_cons (NULL_TREE,
    6049          163 :                                   gfc_convert_expr_to_tree (block, el->expr),
    6050              :                                   thread_limit);
    6051          141 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_THREAD_LIMIT);
    6052          141 :       OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = nreverse (thread_limit);
    6053          141 :       OMP_CLAUSE_THREAD_LIMIT_STRICT (c) = clauses->thread_limit_strict;
    6054          141 :       OMP_CLAUSE_THREAD_LIMIT_DIMS (c) = clauses->thread_limit_dims;
    6055          141 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    6056              :     }
    6057              : 
    6058        32220 :   chunk_size = NULL_TREE;
    6059        32220 :   if (clauses->dist_chunk_size)
    6060              :     {
    6061           81 :       gfc_init_se (&se, NULL);
    6062           81 :       gfc_conv_expr (&se, clauses->dist_chunk_size);
    6063           81 :       gfc_add_block_to_block (block, &se.pre);
    6064           81 :       chunk_size = gfc_evaluate_now (se.expr, block);
    6065           81 :       gfc_add_block_to_block (block, &se.post);
    6066              :     }
    6067              : 
    6068        32220 :   if (clauses->dist_sched_kind != OMP_SCHED_NONE)
    6069              :     {
    6070           94 :       c = build_omp_clause (gfc_get_location (&where),
    6071              :                             OMP_CLAUSE_DIST_SCHEDULE);
    6072           94 :       OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = chunk_size;
    6073           94 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    6074              :     }
    6075              : 
    6076        32220 :   if (clauses->grainsize)
    6077              :     {
    6078           33 :       tree grainsize;
    6079              : 
    6080           33 :       gfc_init_se (&se, NULL);
    6081           33 :       gfc_conv_expr (&se, clauses->grainsize);
    6082           33 :       gfc_add_block_to_block (block, &se.pre);
    6083           33 :       grainsize = gfc_evaluate_now (se.expr, block);
    6084           33 :       gfc_add_block_to_block (block, &se.post);
    6085              : 
    6086           33 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_GRAINSIZE);
    6087           33 :       OMP_CLAUSE_GRAINSIZE_EXPR (c) = grainsize;
    6088           33 :       if (clauses->grainsize_strict)
    6089            1 :         OMP_CLAUSE_GRAINSIZE_STRICT (c) = 1;
    6090           33 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    6091              :     }
    6092              : 
    6093        32220 :   if (clauses->num_tasks)
    6094              :     {
    6095           25 :       tree num_tasks;
    6096              : 
    6097           25 :       gfc_init_se (&se, NULL);
    6098           25 :       gfc_conv_expr (&se, clauses->num_tasks);
    6099           25 :       gfc_add_block_to_block (block, &se.pre);
    6100           25 :       num_tasks = gfc_evaluate_now (se.expr, block);
    6101           25 :       gfc_add_block_to_block (block, &se.post);
    6102              : 
    6103           25 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_TASKS);
    6104           25 :       OMP_CLAUSE_NUM_TASKS_EXPR (c) = num_tasks;
    6105           25 :       if (clauses->num_tasks_strict)
    6106            1 :         OMP_CLAUSE_NUM_TASKS_STRICT (c) = 1;
    6107           25 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    6108              :     }
    6109              : 
    6110        32220 :   if (clauses->priority)
    6111              :     {
    6112           34 :       tree priority;
    6113              : 
    6114           34 :       gfc_init_se (&se, NULL);
    6115           34 :       gfc_conv_expr (&se, clauses->priority);
    6116           34 :       gfc_add_block_to_block (block, &se.pre);
    6117           34 :       priority = gfc_evaluate_now (se.expr, block);
    6118           34 :       gfc_add_block_to_block (block, &se.post);
    6119              : 
    6120           34 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_PRIORITY);
    6121           34 :       OMP_CLAUSE_PRIORITY_EXPR (c) = priority;
    6122           34 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    6123              :     }
    6124              : 
    6125        32220 :   if (clauses->detach)
    6126              :     {
    6127          116 :       tree detach;
    6128              : 
    6129          116 :       gfc_init_se (&se, NULL);
    6130          116 :       gfc_conv_expr (&se, clauses->detach);
    6131          116 :       gfc_add_block_to_block (block, &se.pre);
    6132          116 :       detach = se.expr;
    6133          116 :       gfc_add_block_to_block (block, &se.post);
    6134              : 
    6135          116 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DETACH);
    6136          116 :       TREE_ADDRESSABLE (detach) = 1;
    6137          116 :       OMP_CLAUSE_DECL (c) = detach;
    6138          116 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    6139              :     }
    6140              : 
    6141        32220 :   if (clauses->filter)
    6142              :     {
    6143           31 :       tree filter;
    6144              : 
    6145           31 :       gfc_init_se (&se, NULL);
    6146           31 :       gfc_conv_expr (&se, clauses->filter);
    6147           31 :       gfc_add_block_to_block (block, &se.pre);
    6148           31 :       filter = gfc_evaluate_now (se.expr, block);
    6149           31 :       gfc_add_block_to_block (block, &se.post);
    6150              : 
    6151           31 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_FILTER);
    6152           31 :       OMP_CLAUSE_FILTER_EXPR (c) = filter;
    6153           31 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    6154              :     }
    6155              : 
    6156        32220 :   if (clauses->hint)
    6157              :     {
    6158            8 :       tree hint;
    6159              : 
    6160            8 :       gfc_init_se (&se, NULL);
    6161            8 :       gfc_conv_expr (&se, clauses->hint);
    6162            8 :       gfc_add_block_to_block (block, &se.pre);
    6163            8 :       hint = gfc_evaluate_now (se.expr, block);
    6164            8 :       gfc_add_block_to_block (block, &se.post);
    6165              : 
    6166            8 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_HINT);
    6167            8 :       OMP_CLAUSE_HINT_EXPR (c) = hint;
    6168            8 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    6169              :     }
    6170              : 
    6171        32220 :   if (clauses->simd)
    6172              :     {
    6173           22 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SIMD);
    6174           22 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    6175              :     }
    6176        32220 :   if (clauses->threads)
    6177              :     {
    6178           11 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_THREADS);
    6179           11 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    6180              :     }
    6181        32220 :   if (clauses->nogroup)
    6182              :     {
    6183           13 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NOGROUP);
    6184           13 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    6185              :     }
    6186              : 
    6187       225540 :   for (int i = 0; i < OMP_DEFAULTMAP_CAT_NUM; i++)
    6188              :     {
    6189       193320 :       if (clauses->defaultmap[i] == OMP_DEFAULTMAP_UNSET)
    6190       193168 :        continue;
    6191          152 :       enum omp_clause_defaultmap_kind behavior, category;
    6192          152 :       switch ((gfc_omp_defaultmap_category) i)
    6193              :         {
    6194              :         case OMP_DEFAULTMAP_CAT_UNCATEGORIZED:
    6195              :           category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED;
    6196              :           break;
    6197              :         case OMP_DEFAULTMAP_CAT_ALL:
    6198              :           category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL;
    6199              :           break;
    6200              :         case OMP_DEFAULTMAP_CAT_SCALAR:
    6201              :           category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR;
    6202              :           break;
    6203              :         case OMP_DEFAULTMAP_CAT_AGGREGATE:
    6204              :           category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE;
    6205              :           break;
    6206              :         case OMP_DEFAULTMAP_CAT_ALLOCATABLE:
    6207              :           category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALLOCATABLE;
    6208              :           break;
    6209              :         case OMP_DEFAULTMAP_CAT_POINTER:
    6210              :           category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER;
    6211              :           break;
    6212              :         default: gcc_unreachable ();
    6213              :         }
    6214          152 :       switch (clauses->defaultmap[i])
    6215              :         {
    6216              :         case OMP_DEFAULTMAP_ALLOC:
    6217              :           behavior = OMP_CLAUSE_DEFAULTMAP_ALLOC;
    6218              :           break;
    6219              :         case OMP_DEFAULTMAP_TO: behavior = OMP_CLAUSE_DEFAULTMAP_TO; break;
    6220              :         case OMP_DEFAULTMAP_FROM: behavior = OMP_CLAUSE_DEFAULTMAP_FROM; break;
    6221              :         case OMP_DEFAULTMAP_TOFROM:
    6222              :           behavior = OMP_CLAUSE_DEFAULTMAP_TOFROM;
    6223              :           break;
    6224              :         case OMP_DEFAULTMAP_FIRSTPRIVATE:
    6225              :           behavior = OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE;
    6226              :           break;
    6227              :         case OMP_DEFAULTMAP_PRESENT:
    6228              :           behavior = OMP_CLAUSE_DEFAULTMAP_PRESENT;
    6229              :           break;
    6230              :         case OMP_DEFAULTMAP_NONE: behavior = OMP_CLAUSE_DEFAULTMAP_NONE; break;
    6231              :         case OMP_DEFAULTMAP_DEFAULT:
    6232              :           behavior = OMP_CLAUSE_DEFAULTMAP_DEFAULT;
    6233              :           break;
    6234            0 :         default: gcc_unreachable ();
    6235              :         }
    6236          152 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DEFAULTMAP);
    6237          152 :       OMP_CLAUSE_DEFAULTMAP_SET_KIND (c, behavior, category);
    6238          152 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    6239              :     }
    6240              : 
    6241        32220 :   if (clauses->doacross_source)
    6242              :     {
    6243          132 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DOACROSS);
    6244          132 :       OMP_CLAUSE_DOACROSS_KIND (c) = OMP_CLAUSE_DOACROSS_SOURCE;
    6245          132 :       OMP_CLAUSE_DOACROSS_DEPEND (c) = clauses->depend_source;
    6246          132 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    6247              :     }
    6248              : 
    6249        32220 :   if (clauses->async)
    6250              :     {
    6251          549 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_ASYNC);
    6252          549 :       if (clauses->async_expr)
    6253          549 :         OMP_CLAUSE_ASYNC_EXPR (c)
    6254         1098 :           = gfc_convert_expr_to_tree (block, clauses->async_expr);
    6255              :       else
    6256            0 :         OMP_CLAUSE_ASYNC_EXPR (c) = NULL;
    6257          549 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    6258              :     }
    6259        32220 :   if (clauses->seq)
    6260              :     {
    6261          140 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SEQ);
    6262          140 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    6263              :     }
    6264        32220 :   if (clauses->par_auto)
    6265              :     {
    6266           62 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_AUTO);
    6267           62 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    6268              :     }
    6269        32220 :   if (clauses->if_present)
    6270              :     {
    6271           23 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_IF_PRESENT);
    6272           23 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    6273              :     }
    6274        32220 :   if (clauses->finalize)
    6275              :     {
    6276           23 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_FINALIZE);
    6277           23 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    6278              :     }
    6279        32220 :   if (clauses->independent)
    6280              :     {
    6281          239 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_INDEPENDENT);
    6282          239 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    6283              :     }
    6284        32220 :   if (clauses->wait_list)
    6285              :     {
    6286              :       gfc_expr_list *el;
    6287              : 
    6288          317 :       for (el = clauses->wait_list; el; el = el->next)
    6289              :         {
    6290          172 :           c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_WAIT);
    6291          172 :           OMP_CLAUSE_DECL (c) = gfc_convert_expr_to_tree (block, el->expr);
    6292          172 :           OMP_CLAUSE_CHAIN (c) = omp_clauses;
    6293          172 :           omp_clauses = c;
    6294              :         }
    6295              :     }
    6296        32220 :   if (clauses->num_gangs_expr)
    6297              :     {
    6298          666 :       tree num_gangs_var
    6299          666 :         = gfc_convert_expr_to_tree (block, clauses->num_gangs_expr);
    6300          666 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_GANGS);
    6301          666 :       OMP_CLAUSE_NUM_GANGS_EXPR (c) = num_gangs_var;
    6302          666 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    6303              :     }
    6304        32220 :   if (clauses->num_workers_expr)
    6305              :     {
    6306          583 :       tree num_workers_var
    6307          583 :         = gfc_convert_expr_to_tree (block, clauses->num_workers_expr);
    6308          583 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_WORKERS);
    6309          583 :       OMP_CLAUSE_NUM_WORKERS_EXPR (c) = num_workers_var;
    6310          583 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    6311              :     }
    6312        32220 :   if (clauses->vector_length_expr)
    6313              :     {
    6314          553 :       tree vector_length_var
    6315          553 :         = gfc_convert_expr_to_tree (block, clauses->vector_length_expr);
    6316          553 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_VECTOR_LENGTH);
    6317          553 :       OMP_CLAUSE_VECTOR_LENGTH_EXPR (c) = vector_length_var;
    6318          553 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    6319              :     }
    6320        32220 :   if (clauses->tile_list)
    6321              :     {
    6322              :       tree list = NULL_TREE;
    6323          174 :       for (gfc_expr_list *el = clauses->tile_list; el; el = el->next)
    6324          114 :         list = tree_cons (NULL_TREE, gfc_convert_expr_to_tree (block, el->expr),
    6325              :                           list);
    6326              : 
    6327           60 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_TILE);
    6328           60 :       OMP_CLAUSE_TILE_LIST (c) = nreverse (list);
    6329           60 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    6330              :     }
    6331        32220 :   if (clauses->vector)
    6332              :     {
    6333          835 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_VECTOR);
    6334          835 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    6335              : 
    6336          835 :       if (clauses->vector_expr)
    6337              :         {
    6338          119 :           tree vector_var
    6339          119 :             = gfc_convert_expr_to_tree (block, clauses->vector_expr);
    6340          119 :           OMP_CLAUSE_VECTOR_EXPR (c) = vector_var;
    6341              : 
    6342              :           /* TODO: We're not capturing location information for individual
    6343              :              clauses.  However, if we have an expression attached to the
    6344              :              clause, that one provides better location information.  */
    6345          238 :           OMP_CLAUSE_LOCATION (c)
    6346          119 :             = gfc_get_location (&clauses->vector_expr->where);
    6347              :         }
    6348              :     }
    6349        32220 :   if (clauses->worker)
    6350              :     {
    6351          730 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_WORKER);
    6352          730 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    6353              : 
    6354          730 :       if (clauses->worker_expr)
    6355              :         {
    6356           89 :           tree worker_var
    6357           89 :             = gfc_convert_expr_to_tree (block, clauses->worker_expr);
    6358           89 :           OMP_CLAUSE_WORKER_EXPR (c) = worker_var;
    6359              : 
    6360              :           /* TODO: We're not capturing location information for individual
    6361              :              clauses.  However, if we have an expression attached to the
    6362              :              clause, that one provides better location information.  */
    6363          178 :           OMP_CLAUSE_LOCATION (c)
    6364           89 :             = gfc_get_location (&clauses->worker_expr->where);
    6365              :         }
    6366              :     }
    6367        32220 :   if (clauses->gang)
    6368              :     {
    6369         1011 :       tree arg;
    6370         1011 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_GANG);
    6371         1011 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    6372              : 
    6373         1011 :       if (clauses->gang_num_expr)
    6374              :         {
    6375          101 :           arg = gfc_convert_expr_to_tree (block, clauses->gang_num_expr);
    6376          101 :           OMP_CLAUSE_GANG_EXPR (c) = arg;
    6377              : 
    6378              :           /* TODO: We're not capturing location information for individual
    6379              :              clauses.  However, if we have an expression attached to the
    6380              :              clause, that one provides better location information.  */
    6381          202 :           OMP_CLAUSE_LOCATION (c)
    6382          101 :             = gfc_get_location (&clauses->gang_num_expr->where);
    6383              :         }
    6384              : 
    6385         1011 :       if (clauses->gang_static)
    6386              :         {
    6387           15 :           arg = clauses->gang_static_expr
    6388          104 :             ? gfc_convert_expr_to_tree (block, clauses->gang_static_expr)
    6389              :             : integer_minus_one_node;
    6390          104 :           OMP_CLAUSE_GANG_STATIC_EXPR (c) = arg;
    6391              :         }
    6392              :     }
    6393        32220 :   if (clauses->bind != OMP_BIND_UNSET)
    6394              :     {
    6395           30 :       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_BIND);
    6396           30 :       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
    6397           30 :       switch (clauses->bind)
    6398              :         {
    6399           10 :         case OMP_BIND_TEAMS:
    6400           10 :           OMP_CLAUSE_BIND_KIND (c) = OMP_CLAUSE_BIND_TEAMS;
    6401           10 :           break;
    6402           15 :         case OMP_BIND_PARALLEL:
    6403           15 :           OMP_CLAUSE_BIND_KIND (c) = OMP_CLAUSE_BIND_PARALLEL;
    6404           15 :           break;
    6405            5 :         case OMP_BIND_THREAD:
    6406            5 :           OMP_CLAUSE_BIND_KIND (c) = OMP_CLAUSE_BIND_THREAD;
    6407            5 :           break;
    6408            0 :         default:
    6409            0 :           gcc_unreachable ();
    6410              :         }
    6411              :     }
    6412              :   /* OpenACC 'nohost' clauses cannot appear here.  */
    6413        32220 :   gcc_checking_assert (!clauses->nohost);
    6414              : 
    6415              :   /* OpenACC 'device_num' and 'device_type' clauses cannot appear here.  */
    6416        32220 :   gcc_checking_assert (!clauses->device_num_expr
    6417              :                        && !clauses->oacc_device_type_present);
    6418              : 
    6419        32220 :   return nreverse (omp_clauses);
    6420              : }
    6421              : 
    6422              : /* Like gfc_trans_code, but force creation of a BIND_EXPR around it.  */
    6423              : 
    6424              : static tree
    6425        21409 : gfc_trans_omp_code (gfc_code *code, bool force_empty)
    6426              : {
    6427        21409 :   tree stmt;
    6428              : 
    6429        21409 :   pushlevel ();
    6430        21409 :   stmt = gfc_trans_code (code);
    6431        21409 :   if (TREE_CODE (stmt) != BIND_EXPR)
    6432              :     {
    6433        19015 :       if (!IS_EMPTY_STMT (stmt) || force_empty)
    6434              :         {
    6435        18925 :           tree block = poplevel (1, 0);
    6436        18925 :           stmt = build3_v (BIND_EXPR, NULL, stmt, block);
    6437              :         }
    6438              :       else
    6439           90 :         poplevel (0, 0);
    6440              :     }
    6441              :   else
    6442         2394 :     poplevel (0, 0);
    6443        21409 :   return stmt;
    6444              : }
    6445              : 
    6446              : /* Translate OpenACC 'parallel', 'kernels', 'serial', 'data', 'host_data'
    6447              :    construct. */
    6448              : 
    6449              : static tree
    6450         4189 : gfc_trans_oacc_construct (gfc_code *code)
    6451              : {
    6452         4189 :   stmtblock_t block;
    6453         4189 :   tree stmt, oacc_clauses;
    6454         4189 :   enum tree_code construct_code;
    6455              : 
    6456         4189 :   switch (code->op)
    6457              :     {
    6458              :       case EXEC_OACC_PARALLEL:
    6459              :         construct_code = OACC_PARALLEL;
    6460              :         break;
    6461              :       case EXEC_OACC_KERNELS:
    6462              :         construct_code = OACC_KERNELS;
    6463              :         break;
    6464              :       case EXEC_OACC_SERIAL:
    6465              :         construct_code = OACC_SERIAL;
    6466              :         break;
    6467              :       case EXEC_OACC_DATA:
    6468              :         construct_code = OACC_DATA;
    6469              :         break;
    6470              :       case EXEC_OACC_HOST_DATA:
    6471              :         construct_code = OACC_HOST_DATA;
    6472              :         break;
    6473            0 :       default:
    6474            0 :         gcc_unreachable ();
    6475              :     }
    6476              : 
    6477         4189 :   gfc_start_block (&block);
    6478         4189 :   oacc_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
    6479              :                                         code->loc, false, true);
    6480         4189 :   pushlevel ();
    6481         4189 :   stmt = gfc_trans_omp_code (code->block->next, true);
    6482         4189 :   stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
    6483         4189 :   stmt = build2_loc (gfc_get_location (&code->loc), construct_code,
    6484              :                      void_type_node, stmt, oacc_clauses);
    6485         4189 :   gfc_add_expr_to_block (&block, stmt);
    6486         4189 :   return gfc_finish_block (&block);
    6487              : }
    6488              : 
    6489              : /* update, enter_data, exit_data, cache, init, set, shutdown.  */
    6490              : static tree
    6491         2498 : gfc_trans_oacc_executable_directive (gfc_code *code)
    6492              : {
    6493         2498 :   stmtblock_t block;
    6494         2498 :   tree stmt, oacc_clauses;
    6495         2498 :   enum tree_code construct_code;
    6496              : 
    6497         2498 :   switch (code->op)
    6498              :     {
    6499              :       case EXEC_OACC_UPDATE:
    6500              :         construct_code = OACC_UPDATE;
    6501              :         break;
    6502          787 :       case EXEC_OACC_ENTER_DATA:
    6503          787 :         construct_code = OACC_ENTER_DATA;
    6504          787 :         break;
    6505          575 :       case EXEC_OACC_EXIT_DATA:
    6506          575 :         construct_code = OACC_EXIT_DATA;
    6507          575 :         break;
    6508           76 :       case EXEC_OACC_CACHE:
    6509           76 :         construct_code = OACC_CACHE;
    6510           76 :         break;
    6511          368 :       case EXEC_OACC_INIT:
    6512          368 :       case EXEC_OACC_SHUTDOWN:
    6513          368 :       case EXEC_OACC_SET:
    6514          368 :         goto builtin_oacc_exec_directive;
    6515            0 :       default:
    6516            0 :         gcc_unreachable ();
    6517              :     }
    6518              : 
    6519         2130 :   gfc_start_block (&block);
    6520         2130 :   oacc_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
    6521              :                                         code->loc, false, true, code->op);
    6522         2130 :   stmt = build1_loc (input_location, construct_code, void_type_node,
    6523              :                      oacc_clauses);
    6524         2130 :   gfc_add_expr_to_block (&block, stmt);
    6525         2130 :   return gfc_finish_block (&block);
    6526              : 
    6527          368 : builtin_oacc_exec_directive:
    6528              : 
    6529          368 :   enum built_in_function builtin_code;
    6530              : 
    6531          368 :   switch (code->op)
    6532              :   {
    6533              :     case EXEC_OACC_INIT:
    6534              :       builtin_code = BUILT_IN_GOACC_INIT;
    6535              :       break;
    6536          121 :     case EXEC_OACC_SHUTDOWN:
    6537          121 :       builtin_code = BUILT_IN_GOACC_SHUTDOWN;
    6538          121 :       break;
    6539          119 :     case EXEC_OACC_SET:
    6540          119 :       builtin_code = BUILT_IN_GOACC_SET_DEVICE;
    6541          119 :       break;
    6542              :     default:
    6543              :       gcc_unreachable ();
    6544              :   }
    6545              : 
    6546          368 :   location_t loc = input_location;
    6547          368 :   gfc_omp_clauses *clauses = code->ext.omp_clauses;
    6548              : 
    6549          368 :   gfc_start_block (&block);
    6550              : 
    6551          368 :   tree n_device;
    6552          368 :   if (clauses->device_num_expr)
    6553          105 :     n_device = gfc_convert_expr_to_tree (&block, clauses->device_num_expr);
    6554              :   else
    6555              :     /* no 'device_num' clause specified by
    6556              :        the user, we don't modify the value of ICV
    6557              :        'acc-current-device-num-var' or we do not
    6558              :        take any action in init and shutdown directive
    6559              :        using -1 value.  */
    6560          263 :     n_device = build_int_cst (integer_type_node, -1);
    6561              : 
    6562              :   /* GOMP_DEVICE_NONE is used to make the operation
    6563              :      in all the devices.
    6564              : 
    6565              :      GOMP_DEVICE_DEFAULT is used in set directive
    6566              :      to do nothing if the clause do not appear.  */
    6567          368 :   int device_type = code->op == EXEC_OACC_SET ?
    6568              :                     GOMP_DEVICE_DEFAULT       :
    6569              :                     GOMP_DEVICE_NONE;
    6570          368 :   if (clauses->oacc_device_type_present)
    6571          324 :     device_type = clauses->oacc_device_type;
    6572              : 
    6573          368 :   tree d_type = build_int_cst (integer_type_node, device_type);
    6574              : 
    6575          368 :   stmt = builtin_decl_explicit (builtin_code);
    6576              : 
    6577          368 :   stmt = build_call_expr_loc (loc, stmt, 2, n_device, d_type);
    6578              : 
    6579          368 :   if (clauses->if_expr)
    6580          108 :     stmt = build3_loc (input_location, COND_EXPR, void_type_node,
    6581              :                        gfc_convert_expr_to_tree (&block, clauses->if_expr),
    6582              :                        stmt, NULL_TREE);
    6583              : 
    6584          368 :   gfc_add_expr_to_block (&block, stmt);
    6585              : 
    6586          368 :   return gfc_finish_block (&block);
    6587              : }
    6588              : 
    6589              : static tree
    6590          173 : gfc_trans_oacc_wait_directive (gfc_code *code)
    6591              : {
    6592          173 :   stmtblock_t block;
    6593          173 :   tree stmt, t;
    6594          173 :   vec<tree, va_gc> *args;
    6595          173 :   int nparms = 0;
    6596          173 :   gfc_expr_list *el;
    6597          173 :   gfc_omp_clauses *clauses = code->ext.omp_clauses;
    6598          173 :   location_t loc = input_location;
    6599              : 
    6600          303 :   for (el = clauses->wait_list; el; el = el->next)
    6601          130 :     nparms++;
    6602              : 
    6603          173 :   vec_alloc (args, nparms + 2);
    6604          173 :   stmt = builtin_decl_explicit (BUILT_IN_GOACC_WAIT);
    6605              : 
    6606          173 :   gfc_start_block (&block);
    6607              : 
    6608          173 :   if (clauses->async_expr)
    6609            3 :     t = gfc_convert_expr_to_tree (&block, clauses->async_expr);
    6610              :   else
    6611          170 :     t = build_int_cst (integer_type_node, -2);
    6612              : 
    6613          173 :   args->quick_push (t);
    6614          173 :   args->quick_push (build_int_cst (integer_type_node, nparms));
    6615              : 
    6616          303 :   for (el = clauses->wait_list; el; el = el->next)
    6617          130 :     args->quick_push (gfc_convert_expr_to_tree (&block, el->expr));
    6618              : 
    6619          173 :   stmt = build_call_expr_loc_vec (loc, stmt, args);
    6620          173 :   if (clauses->if_expr)
    6621            6 :     stmt = build3_loc (input_location, COND_EXPR, void_type_node,
    6622              :                        gfc_convert_expr_to_tree (&block, clauses->if_expr),
    6623              :                        stmt, NULL_TREE);
    6624          173 :   gfc_add_expr_to_block (&block, stmt);
    6625              : 
    6626          173 :   vec_free (args);
    6627              : 
    6628          173 :   return gfc_finish_block (&block);
    6629              : }
    6630              : 
    6631              : static tree gfc_trans_omp_sections (gfc_code *, gfc_omp_clauses *);
    6632              : static tree gfc_trans_omp_workshare (gfc_code *, gfc_omp_clauses *);
    6633              : 
    6634              : static tree
    6635           35 : gfc_trans_omp_allocators (gfc_code *code)
    6636              : {
    6637           35 :   static bool warned = false;
    6638           35 :   gfc_omp_namelist *omp_allocate
    6639           35 :     = code->ext.omp_clauses->lists[OMP_LIST_ALLOCATE];
    6640           35 :   if (!flag_openmp_allocators && !warned)
    6641              :     {
    6642            3 :       omp_allocate = NULL;
    6643            3 :       gfc_error ("%<!$OMP %s%> at %L requires %<-fopenmp-allocators%>",
    6644            3 :                  code->op == EXEC_OMP_ALLOCATE ? "ALLOCATE" : "ALLOCATORS",
    6645              :                  &code->loc);
    6646            3 :       warning (0, "All files that might deallocate such a variable must be "
    6647              :                   "compiled with %<-fopenmp-allocators%>");
    6648            3 :       inform (UNKNOWN_LOCATION,
    6649              :               "This includes explicit DEALLOCATE, reallocation on intrinsic "
    6650              :               "assignment, INTENT(OUT) for allocatable dummy arguments, and "
    6651              :               "reallocation of allocatable components allocated with an "
    6652              :               "OpenMP allocator");
    6653            3 :       warned = true;
    6654              :     }
    6655           35 :   return gfc_trans_allocate (code->block->next, omp_allocate);
    6656              : }
    6657              : 
    6658              : static tree
    6659           10 : gfc_trans_omp_assume (gfc_code *code)
    6660              : {
    6661           10 :   stmtblock_t block;
    6662           10 :   gfc_init_block (&block);
    6663           10 :   gfc_omp_assumptions *assume = code->ext.omp_clauses->assume;
    6664           10 :   if (assume)
    6665           19 :     for (gfc_expr_list *el = assume->holds; el; el = el->next)
    6666              :       {
    6667            9 :         location_t loc = gfc_get_location (&el->expr->where);
    6668            9 :         gfc_se se;
    6669            9 :         gfc_init_se (&se, NULL);
    6670            9 :         gfc_conv_expr (&se, el->expr);
    6671            9 :         tree t;
    6672            9 :         if (se.pre.head == NULL_TREE && se.post.head == NULL_TREE)
    6673            8 :           t = se.expr;
    6674              :         else
    6675              :           {
    6676            1 :             tree var = create_tmp_var_raw (boolean_type_node);
    6677            1 :             DECL_CONTEXT (var) = current_function_decl;
    6678            1 :             stmtblock_t block2;
    6679            1 :             gfc_init_block (&block2);
    6680            1 :             gfc_add_block_to_block (&block2, &se.pre);
    6681            1 :             gfc_add_modify_loc (loc, &block2, var,
    6682              :                                 fold_convert_loc (loc, boolean_type_node,
    6683              :                                                   se.expr));
    6684            1 :             gfc_add_block_to_block (&block2, &se.post);
    6685            1 :             t = gfc_finish_block (&block2);
    6686            1 :             t = build4 (TARGET_EXPR, boolean_type_node, var, t, NULL, NULL);
    6687              :           }
    6688            9 :         t = build_call_expr_internal_loc (loc, IFN_ASSUME,
    6689              :                                           void_type_node, 1, t);
    6690            9 :         gfc_add_expr_to_block (&block, t);
    6691              :       }
    6692           10 :   gfc_add_expr_to_block (&block, gfc_trans_omp_code (code->block->next, true));
    6693           10 :   return gfc_finish_block (&block);
    6694              : }
    6695              : 
    6696              : static tree
    6697         2596 : gfc_trans_omp_atomic (gfc_code *code)
    6698              : {
    6699         2596 :   gfc_code *atomic_code = code->block;
    6700         2596 :   gfc_se lse;
    6701         2596 :   gfc_se rse;
    6702         2596 :   gfc_se vse;
    6703         2596 :   gfc_expr *expr1, *expr2, *e, *capture_expr1 = NULL, *capture_expr2 = NULL;
    6704         2596 :   gfc_symbol *var;
    6705         2596 :   stmtblock_t block;
    6706         2596 :   tree lhsaddr, type, rhs, x, compare = NULL_TREE, comp_tgt = NULL_TREE;
    6707         2596 :   enum tree_code op = ERROR_MARK;
    6708         2596 :   enum tree_code aop = OMP_ATOMIC;
    6709         2596 :   bool var_on_left = false, else_branch = false;
    6710         2596 :   enum omp_memory_order mo, fail_mo;
    6711         2596 :   switch (atomic_code->ext.omp_clauses->memorder)
    6712              :     {
    6713              :     case OMP_MEMORDER_UNSET: mo = OMP_MEMORY_ORDER_UNSPECIFIED; break;
    6714              :     case OMP_MEMORDER_ACQ_REL: mo = OMP_MEMORY_ORDER_ACQ_REL; break;
    6715              :     case OMP_MEMORDER_ACQUIRE: mo = OMP_MEMORY_ORDER_ACQUIRE; break;
    6716              :     case OMP_MEMORDER_RELAXED: mo = OMP_MEMORY_ORDER_RELAXED; break;
    6717              :     case OMP_MEMORDER_RELEASE: mo = OMP_MEMORY_ORDER_RELEASE; break;
    6718              :     case OMP_MEMORDER_SEQ_CST: mo = OMP_MEMORY_ORDER_SEQ_CST; break;
    6719            0 :     default: gcc_unreachable ();
    6720              :     }
    6721         2596 :   switch (atomic_code->ext.omp_clauses->fail)
    6722              :     {
    6723              :     case OMP_MEMORDER_UNSET: fail_mo = OMP_FAIL_MEMORY_ORDER_UNSPECIFIED; break;
    6724           14 :     case OMP_MEMORDER_ACQUIRE: fail_mo = OMP_FAIL_MEMORY_ORDER_ACQUIRE; break;
    6725           26 :     case OMP_MEMORDER_RELAXED: fail_mo = OMP_FAIL_MEMORY_ORDER_RELAXED; break;
    6726            2 :     case OMP_MEMORDER_SEQ_CST: fail_mo = OMP_FAIL_MEMORY_ORDER_SEQ_CST; break;
    6727            0 :     default: gcc_unreachable ();
    6728              :     }
    6729         2596 :   mo = (omp_memory_order) (mo | fail_mo);
    6730              : 
    6731         2596 :   code = code->block->next;
    6732         2596 :   if (atomic_code->ext.omp_clauses->compare)
    6733              :     {
    6734          144 :       gfc_expr *comp_expr;
    6735          144 :       if (code->op == EXEC_IF)
    6736              :         {
    6737          125 :           comp_expr = code->block->expr1;
    6738          125 :           gcc_assert (code->block->next->op == EXEC_ASSIGN);
    6739          125 :           expr1 = code->block->next->expr1;
    6740          125 :           expr2 = code->block->next->expr2;
    6741          125 :           if (code->block->block)
    6742              :             {
    6743           64 :               gcc_assert (atomic_code->ext.omp_clauses->capture
    6744              :                           && code->block->block->next->op == EXEC_ASSIGN);
    6745           64 :               else_branch = true;
    6746           64 :               aop = OMP_ATOMIC_CAPTURE_OLD;
    6747           64 :               capture_expr1 = code->block->block->next->expr1;
    6748           64 :               capture_expr2 = code->block->block->next->expr2;
    6749              :             }
    6750           61 :           else if (atomic_code->ext.omp_clauses->capture)
    6751              :             {
    6752           19 :               gcc_assert (code->next->op == EXEC_ASSIGN);
    6753           19 :               aop = OMP_ATOMIC_CAPTURE_NEW;
    6754           19 :               capture_expr1 = code->next->expr1;
    6755           19 :               capture_expr2 = code->next->expr2;
    6756              :             }
    6757              :         }
    6758              :       else
    6759              :         {
    6760           19 :           gcc_assert (atomic_code->ext.omp_clauses->capture
    6761              :                       && code->op == EXEC_ASSIGN
    6762              :                       && code->next->op == EXEC_IF);
    6763           19 :           aop = OMP_ATOMIC_CAPTURE_OLD;
    6764           19 :           capture_expr1 = code->expr1;
    6765           19 :           capture_expr2 = code->expr2;
    6766           19 :           expr1 = code->next->block->next->expr1;
    6767           19 :           expr2 = code->next->block->next->expr2;
    6768           19 :           comp_expr = code->next->block->expr1;
    6769              :         }
    6770          144 :       gfc_init_se (&lse, NULL);
    6771          144 :       gfc_conv_expr (&lse, comp_expr->value.op.op2);
    6772          144 :       gfc_add_block_to_block (&block, &lse.pre);
    6773          144 :       compare = lse.expr;
    6774          144 :       var = expr1->symtree->n.sym;
    6775              :     }
    6776              :   else
    6777              :     {
    6778         2452 :       gcc_assert (code->op == EXEC_ASSIGN);
    6779         2452 :       expr1 = code->expr1;
    6780         2452 :       expr2 = code->expr2;
    6781         2452 :       if (atomic_code->ext.omp_clauses->capture
    6782          463 :           && (expr2->expr_type == EXPR_VARIABLE
    6783          245 :               || (expr2->expr_type == EXPR_FUNCTION
    6784          113 :                   && expr2->value.function.isym
    6785          113 :                   && expr2->value.function.isym->id == GFC_ISYM_CONVERSION
    6786           41 :                   && (expr2->value.function.actual->expr->expr_type
    6787              :                       == EXPR_VARIABLE))))
    6788              :         {
    6789          235 :           capture_expr1 = expr1;
    6790          235 :           capture_expr2 = expr2;
    6791          235 :           expr1 = code->next->expr1;
    6792          235 :           expr2 = code->next->expr2;
    6793          235 :           aop = OMP_ATOMIC_CAPTURE_OLD;
    6794              :         }
    6795         2217 :       else if (atomic_code->ext.omp_clauses->capture)
    6796              :         {
    6797          228 :           aop = OMP_ATOMIC_CAPTURE_NEW;
    6798          228 :           capture_expr1 = code->next->expr1;
    6799          228 :           capture_expr2 = code->next->expr2;
    6800              :         }
    6801         2452 :       var = expr1->symtree->n.sym;
    6802              :     }
    6803              : 
    6804         2596 :   gfc_init_se (&lse, NULL);
    6805         2596 :   gfc_init_se (&rse, NULL);
    6806         2596 :   gfc_init_se (&vse, NULL);
    6807         2596 :   gfc_start_block (&block);
    6808              : 
    6809         2596 :   if (((atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_MASK)
    6810              :        != GFC_OMP_ATOMIC_WRITE)
    6811         2190 :       && expr2->expr_type == EXPR_FUNCTION
    6812          472 :       && expr2->value.function.isym
    6813          472 :       && expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
    6814          139 :     expr2 = expr2->value.function.actual->expr;
    6815              : 
    6816         2596 :   if ((atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_MASK)
    6817              :       == GFC_OMP_ATOMIC_READ)
    6818              :     {
    6819          494 :       gfc_conv_expr (&vse, expr1);
    6820          494 :       gfc_add_block_to_block (&block, &vse.pre);
    6821              : 
    6822          494 :       gfc_conv_expr (&lse, expr2);
    6823          494 :       gfc_add_block_to_block (&block, &lse.pre);
    6824          494 :       type = TREE_TYPE (lse.expr);
    6825          494 :       lhsaddr = gfc_build_addr_expr (NULL, lse.expr);
    6826              : 
    6827          494 :       x = build1 (OMP_ATOMIC_READ, type, lhsaddr);
    6828          494 :       OMP_ATOMIC_MEMORY_ORDER (x) = mo;
    6829          494 :       x = convert (TREE_TYPE (vse.expr), x);
    6830          494 :       gfc_add_modify (&block, vse.expr, x);
    6831              : 
    6832          494 :       gfc_add_block_to_block (&block, &lse.pre);
    6833          494 :       gfc_add_block_to_block (&block, &rse.pre);
    6834              : 
    6835          494 :       return gfc_finish_block (&block);
    6836              :     }
    6837              : 
    6838         2102 :   if (capture_expr2
    6839          565 :       && capture_expr2->expr_type == EXPR_FUNCTION
    6840           21 :       && capture_expr2->value.function.isym
    6841           21 :       && capture_expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
    6842           21 :     capture_expr2 = capture_expr2->value.function.actual->expr;
    6843          565 :   gcc_assert (!capture_expr2 || capture_expr2->expr_type == EXPR_VARIABLE);
    6844              : 
    6845         2102 :   if (aop == OMP_ATOMIC_CAPTURE_OLD)
    6846              :     {
    6847          318 :       gfc_conv_expr (&vse, capture_expr1);
    6848          318 :       gfc_add_block_to_block (&block, &vse.pre);
    6849          318 :       gfc_conv_expr (&lse, capture_expr2);
    6850          318 :       gfc_add_block_to_block (&block, &lse.pre);
    6851          318 :       gfc_init_se (&lse, NULL);
    6852              :     }
    6853              : 
    6854         2102 :   gfc_conv_expr (&lse, expr1);
    6855         2102 :   gfc_add_block_to_block (&block, &lse.pre);
    6856         2102 :   type = TREE_TYPE (lse.expr);
    6857         2102 :   lhsaddr = gfc_build_addr_expr (NULL, lse.expr);
    6858              : 
    6859         2102 :   if (((atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_MASK)
    6860              :        == GFC_OMP_ATOMIC_WRITE)
    6861         1696 :       || (atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_SWAP)
    6862         1674 :       || compare)
    6863              :     {
    6864          572 :       gfc_conv_expr (&rse, expr2);
    6865          572 :       gfc_add_block_to_block (&block, &rse.pre);
    6866              :     }
    6867         1530 :   else if (expr2->expr_type == EXPR_OP)
    6868              :     {
    6869         1184 :       gfc_expr *e;
    6870         1184 :       switch (expr2->value.op.op)
    6871              :         {
    6872              :         case INTRINSIC_PLUS:
    6873              :           op = PLUS_EXPR;
    6874              :           break;
    6875           91 :         case INTRINSIC_TIMES:
    6876           91 :           op = MULT_EXPR;
    6877           91 :           break;
    6878          113 :         case INTRINSIC_MINUS:
    6879          113 :           op = MINUS_EXPR;
    6880          113 :           break;
    6881           91 :         case INTRINSIC_DIVIDE:
    6882           91 :           if (expr2->ts.type == BT_INTEGER)
    6883              :             op = TRUNC_DIV_EXPR;
    6884              :           else
    6885           74 :             op = RDIV_EXPR;
    6886              :           break;
    6887           43 :         case INTRINSIC_AND:
    6888           43 :           op = TRUTH_ANDIF_EXPR;
    6889           43 :           break;
    6890           49 :         case INTRINSIC_OR:
    6891           49 :           op = TRUTH_ORIF_EXPR;
    6892           49 :           break;
    6893           43 :         case INTRINSIC_EQV:
    6894           43 :           op = EQ_EXPR;
    6895           43 :           break;
    6896           43 :         case INTRINSIC_NEQV:
    6897           43 :           op = NE_EXPR;
    6898           43 :           break;
    6899            0 :         default:
    6900            0 :           gcc_unreachable ();
    6901              :         }
    6902         1184 :       e = expr2->value.op.op1;
    6903         1184 :       if (e->expr_type == EXPR_FUNCTION
    6904           48 :           && e->value.function.isym
    6905           48 :           && e->value.function.isym->id == GFC_ISYM_CONVERSION)
    6906           48 :         e = e->value.function.actual->expr;
    6907         1184 :       if (e->expr_type == EXPR_VARIABLE
    6908          925 :           && e->symtree != NULL
    6909          925 :           && e->symtree->n.sym == var)
    6910              :         {
    6911          910 :           expr2 = expr2->value.op.op2;
    6912          910 :           var_on_left = true;
    6913              :         }
    6914              :       else
    6915              :         {
    6916          274 :           e = expr2->value.op.op2;
    6917          274 :           if (e->expr_type == EXPR_FUNCTION
    6918           48 :               && e->value.function.isym
    6919           48 :               && e->value.function.isym->id == GFC_ISYM_CONVERSION)
    6920           48 :             e = e->value.function.actual->expr;
    6921          274 :           gcc_assert (e->expr_type == EXPR_VARIABLE
    6922              :                       && e->symtree != NULL
    6923              :                       && e->symtree->n.sym == var);
    6924              :           expr2 = expr2->value.op.op1;
    6925              :           var_on_left = false;
    6926              :         }
    6927         1184 :       gfc_conv_expr (&rse, expr2);
    6928         1184 :       gfc_add_block_to_block (&block, &rse.pre);
    6929              :     }
    6930              :   else
    6931              :     {
    6932          346 :       gcc_assert (expr2->expr_type == EXPR_FUNCTION);
    6933          346 :       switch (expr2->value.function.isym->id)
    6934              :         {
    6935              :         case GFC_ISYM_MIN:
    6936              :           op = MIN_EXPR;
    6937              :           break;
    6938          114 :         case GFC_ISYM_MAX:
    6939          114 :           op = MAX_EXPR;
    6940          114 :           break;
    6941           47 :         case GFC_ISYM_IAND:
    6942           47 :           op = BIT_AND_EXPR;
    6943           47 :           break;
    6944           49 :         case GFC_ISYM_IOR:
    6945           49 :           op = BIT_IOR_EXPR;
    6946           49 :           break;
    6947           45 :         case GFC_ISYM_IEOR:
    6948           45 :           op = BIT_XOR_EXPR;
    6949           45 :           break;
    6950            0 :         default:
    6951            0 :           gcc_unreachable ();
    6952              :         }
    6953          346 :       e = expr2->value.function.actual->expr;
    6954          346 :       if (e->expr_type == EXPR_FUNCTION
    6955           13 :           && e->value.function.isym
    6956           13 :           && e->value.function.isym->id == GFC_ISYM_CONVERSION)
    6957           13 :         e = e->value.function.actual->expr;
    6958          346 :       gcc_assert (e->expr_type == EXPR_VARIABLE
    6959              :                   && e->symtree != NULL
    6960              :                   && e->symtree->n.sym == var);
    6961              : 
    6962          346 :       gfc_conv_expr (&rse, expr2->value.function.actual->next->expr);
    6963          346 :       gfc_add_block_to_block (&block, &rse.pre);
    6964          346 :       if (expr2->value.function.actual->next->next != NULL)
    6965              :         {
    6966           26 :           tree accum = gfc_create_var (TREE_TYPE (rse.expr), NULL);
    6967           26 :           gfc_actual_arglist *arg;
    6968              : 
    6969           26 :           gfc_add_modify (&block, accum, rse.expr);
    6970           64 :           for (arg = expr2->value.function.actual->next->next; arg;
    6971           38 :                arg = arg->next)
    6972              :             {
    6973           38 :               gfc_init_block (&rse.pre);
    6974           38 :               gfc_conv_expr (&rse, arg->expr);
    6975           38 :               gfc_add_block_to_block (&block, &rse.pre);
    6976           38 :               x = fold_build2_loc (input_location, op, TREE_TYPE (accum),
    6977              :                                    accum, rse.expr);
    6978           38 :               gfc_add_modify (&block, accum, x);
    6979              :             }
    6980              : 
    6981           26 :           rse.expr = accum;
    6982              :         }
    6983              : 
    6984          346 :       expr2 = expr2->value.function.actual->next->expr;
    6985              :     }
    6986              : 
    6987         2102 :   lhsaddr = save_expr (lhsaddr);
    6988         2102 :   if (TREE_CODE (lhsaddr) != SAVE_EXPR
    6989         2102 :       && (TREE_CODE (lhsaddr) != ADDR_EXPR
    6990         1642 :           || !VAR_P (TREE_OPERAND (lhsaddr, 0))))
    6991              :     {
    6992              :       /* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize
    6993              :          it even after unsharing function body.  */
    6994           44 :       tree var = create_tmp_var_raw (TREE_TYPE (lhsaddr));
    6995           44 :       DECL_CONTEXT (var) = current_function_decl;
    6996           44 :       lhsaddr = build4 (TARGET_EXPR, TREE_TYPE (lhsaddr), var, lhsaddr,
    6997              :                         NULL_TREE, NULL_TREE);
    6998              :     }
    6999              : 
    7000         2102 :   if (compare)
    7001              :     {
    7002          144 :       tree var = create_tmp_var_raw (TREE_TYPE (lhsaddr));
    7003          144 :       DECL_CONTEXT (var) = current_function_decl;
    7004          144 :       lhsaddr = build4 (TARGET_EXPR, TREE_TYPE (lhsaddr), var, lhsaddr, NULL,
    7005              :                         NULL);
    7006          144 :       lse.expr = build_fold_indirect_ref_loc (input_location, lhsaddr);
    7007          144 :       compare = convert (TREE_TYPE (lse.expr), compare);
    7008          144 :       compare = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
    7009              :                                  lse.expr, compare);
    7010              :     }
    7011              : 
    7012         2102 :   if (expr2->expr_type == EXPR_VARIABLE || compare)
    7013          460 :     rhs = rse.expr;
    7014              :   else
    7015         1642 :     rhs = gfc_evaluate_now (rse.expr, &block);
    7016              : 
    7017         2102 :   if (((atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_MASK)
    7018              :        == GFC_OMP_ATOMIC_WRITE)
    7019         1696 :       || (atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_SWAP)
    7020         1674 :       || compare)
    7021              :     x = rhs;
    7022              :   else
    7023              :     {
    7024         1530 :       x = convert (TREE_TYPE (rhs),
    7025              :                    build_fold_indirect_ref_loc (input_location, lhsaddr));
    7026         1530 :       if (var_on_left)
    7027          910 :         x = fold_build2_loc (input_location, op, TREE_TYPE (rhs), x, rhs);
    7028              :       else
    7029          620 :         x = fold_build2_loc (input_location, op, TREE_TYPE (rhs), rhs, x);
    7030              :     }
    7031              : 
    7032         2102 :   if (TREE_CODE (TREE_TYPE (rhs)) == COMPLEX_TYPE
    7033         2102 :       && TREE_CODE (type) != COMPLEX_TYPE)
    7034            0 :     x = fold_build1_loc (input_location, REALPART_EXPR,
    7035            0 :                          TREE_TYPE (TREE_TYPE (rhs)), x);
    7036              : 
    7037         2102 :   gfc_add_block_to_block (&block, &lse.pre);
    7038         2102 :   gfc_add_block_to_block (&block, &rse.pre);
    7039              : 
    7040         2102 :   if (aop == OMP_ATOMIC_CAPTURE_NEW)
    7041              :     {
    7042          247 :       gfc_conv_expr (&vse, capture_expr1);
    7043          247 :       gfc_add_block_to_block (&block, &vse.pre);
    7044          247 :       gfc_add_block_to_block (&block, &lse.pre);
    7045              :     }
    7046              : 
    7047         2102 :   if (compare && else_branch)
    7048              :     {
    7049           64 :       tree var2 = create_tmp_var_raw (boolean_type_node);
    7050           64 :       DECL_CONTEXT (var2) = current_function_decl;
    7051           64 :       comp_tgt = build4 (TARGET_EXPR, boolean_type_node, var2,
    7052              :                          boolean_false_node, NULL, NULL);
    7053           64 :       compare = fold_build2_loc (input_location, MODIFY_EXPR, TREE_TYPE (var2),
    7054              :                                  var2, compare);
    7055           64 :       TREE_OPERAND (compare, 0) = comp_tgt;
    7056           64 :       compare = omit_one_operand_loc (input_location, boolean_type_node,
    7057              :                                       compare, comp_tgt);
    7058              :     }
    7059              : 
    7060         2102 :   if (compare)
    7061          144 :     x = build3_loc (input_location, COND_EXPR, type, compare,
    7062              :                     convert (type, x), lse.expr);
    7063              : 
    7064         2102 :   if (aop == OMP_ATOMIC)
    7065              :     {
    7066         1537 :       x = build2_v (OMP_ATOMIC, lhsaddr, convert (type, x));
    7067         1537 :       OMP_ATOMIC_MEMORY_ORDER (x) = mo;
    7068         1537 :       OMP_ATOMIC_WEAK (x) = atomic_code->ext.omp_clauses->weak;
    7069         1537 :       gfc_add_expr_to_block (&block, x);
    7070              :     }
    7071              :   else
    7072              :     {
    7073          565 :       x = build2 (aop, type, lhsaddr, convert (type, x));
    7074          565 :       OMP_ATOMIC_MEMORY_ORDER (x) = mo;
    7075          565 :       OMP_ATOMIC_WEAK (x) = atomic_code->ext.omp_clauses->weak;
    7076          565 :       if (compare && else_branch)
    7077              :         {
    7078           64 :           tree vtmp = create_tmp_var_raw (TREE_TYPE (x));
    7079           64 :           DECL_CONTEXT (vtmp) = current_function_decl;
    7080           64 :           x = fold_build2_loc (input_location, MODIFY_EXPR,
    7081           64 :                                TREE_TYPE (vtmp), vtmp, x);
    7082           64 :           vtmp = build4 (TARGET_EXPR, TREE_TYPE (vtmp), vtmp,
    7083           64 :                          build_zero_cst (TREE_TYPE (vtmp)), NULL, NULL);
    7084           64 :           TREE_OPERAND (x, 0) = vtmp;
    7085           64 :           tree x2 = convert (TREE_TYPE (vse.expr), vtmp);
    7086           64 :           x2 = fold_build2_loc (input_location, MODIFY_EXPR,
    7087           64 :                                TREE_TYPE (vse.expr), vse.expr, x2);
    7088           64 :           x2 = build3_loc (input_location, COND_EXPR, void_type_node, comp_tgt,
    7089              :                            void_node, x2);
    7090           64 :           x = omit_one_operand_loc (input_location, TREE_TYPE (x2), x2, x);
    7091           64 :           gfc_add_expr_to_block (&block, x);
    7092              :         }
    7093              :       else
    7094              :         {
    7095          501 :           x = convert (TREE_TYPE (vse.expr), x);
    7096          501 :           gfc_add_modify (&block, vse.expr, x);
    7097              :         }
    7098              :     }
    7099              : 
    7100         2102 :   return gfc_finish_block (&block);
    7101              : }
    7102              : 
    7103              : static tree
    7104          604 : gfc_trans_omp_barrier (void)
    7105              : {
    7106          604 :   tree decl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER);
    7107          604 :   return build_call_expr_loc (input_location, decl, 1,
    7108              :                               build_int_cst (integer_type_node,
    7109          604 :                                              GOMP_BARRIER_EXPLICIT));
    7110              : }
    7111              : 
    7112              : static tree
    7113          310 : gfc_trans_omp_cancel (gfc_code *code)
    7114              : {
    7115          310 :   int mask = 0;
    7116          310 :   tree ifc = boolean_true_node;
    7117          310 :   stmtblock_t block;
    7118          310 :   switch (code->ext.omp_clauses->cancel)
    7119              :     {
    7120              :     case OMP_CANCEL_PARALLEL: mask = 1; break;
    7121              :     case OMP_CANCEL_DO: mask = 2; break;
    7122              :     case OMP_CANCEL_SECTIONS: mask = 4; break;
    7123              :     case OMP_CANCEL_TASKGROUP: mask = 8; break;
    7124            0 :     default: gcc_unreachable ();
    7125              :     }
    7126          310 :   gfc_start_block (&block);
    7127          310 :   if (code->ext.omp_clauses->if_expr
    7128          219 :       || code->ext.omp_clauses->if_exprs[OMP_IF_CANCEL])
    7129              :     {
    7130           99 :       gfc_se se;
    7131           99 :       tree if_var;
    7132              : 
    7133           99 :       gcc_assert ((code->ext.omp_clauses->if_expr == NULL)
    7134              :                   ^ (code->ext.omp_clauses->if_exprs[OMP_IF_CANCEL] == NULL));
    7135           99 :       gfc_init_se (&se, NULL);
    7136           99 :       gfc_conv_expr (&se, code->ext.omp_clauses->if_expr != NULL
    7137              :                           ? code->ext.omp_clauses->if_expr
    7138              :                           : code->ext.omp_clauses->if_exprs[OMP_IF_CANCEL]);
    7139           99 :       gfc_add_block_to_block (&block, &se.pre);
    7140           99 :       if_var = gfc_evaluate_now (se.expr, &block);
    7141           99 :       gfc_add_block_to_block (&block, &se.post);
    7142           99 :       tree type = TREE_TYPE (if_var);
    7143           99 :       ifc = fold_build2_loc (input_location, NE_EXPR,
    7144              :                              boolean_type_node, if_var,
    7145              :                              build_zero_cst (type));
    7146              :     }
    7147          310 :   tree decl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
    7148          310 :   tree c_bool_type = TREE_TYPE (TREE_TYPE (decl));
    7149          310 :   ifc = fold_convert (c_bool_type, ifc);
    7150          310 :   gfc_add_expr_to_block (&block,
    7151              :                          build_call_expr_loc (input_location, decl, 2,
    7152              :                                               build_int_cst (integer_type_node,
    7153          310 :                                                              mask), ifc));
    7154          310 :   return gfc_finish_block (&block);
    7155              : }
    7156              : 
    7157              : static tree
    7158          170 : gfc_trans_omp_cancellation_point (gfc_code *code)
    7159              : {
    7160          170 :   int mask = 0;
    7161          170 :   switch (code->ext.omp_clauses->cancel)
    7162              :     {
    7163              :     case OMP_CANCEL_PARALLEL: mask = 1; break;
    7164              :     case OMP_CANCEL_DO: mask = 2; break;
    7165              :     case OMP_CANCEL_SECTIONS: mask = 4; break;
    7166              :     case OMP_CANCEL_TASKGROUP: mask = 8; break;
    7167            0 :     default: gcc_unreachable ();
    7168              :     }
    7169          170 :   tree decl = builtin_decl_explicit (BUILT_IN_GOMP_CANCELLATION_POINT);
    7170          170 :   return build_call_expr_loc (input_location, decl, 1,
    7171          340 :                               build_int_cst (integer_type_node, mask));
    7172              : }
    7173              : 
    7174              : static tree
    7175          143 : gfc_trans_omp_critical (gfc_code *code)
    7176              : {
    7177          143 :   stmtblock_t block;
    7178          143 :   tree stmt, name = NULL_TREE;
    7179          143 :   if (code->ext.omp_clauses->critical_name != NULL)
    7180           36 :     name = get_identifier (code->ext.omp_clauses->critical_name);
    7181          143 :   gfc_start_block (&block);
    7182          143 :   stmt = make_node (OMP_CRITICAL);
    7183          143 :   SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc));
    7184          143 :   TREE_TYPE (stmt) = void_type_node;
    7185          143 :   OMP_CRITICAL_BODY (stmt) = gfc_trans_code (code->block->next);
    7186          143 :   OMP_CRITICAL_NAME (stmt) = name;
    7187          143 :   OMP_CRITICAL_CLAUSES (stmt) = gfc_trans_omp_clauses (&block,
    7188              :                                                        code->ext.omp_clauses,
    7189              :                                                        code->loc);
    7190          143 :   gfc_add_expr_to_block (&block, stmt);
    7191          143 :   return gfc_finish_block (&block);
    7192              : }
    7193              : 
    7194              : typedef struct dovar_init_d {
    7195              :   gfc_symbol *sym;
    7196              :   tree var;
    7197              :   tree init;
    7198              :   bool non_unit_iter;
    7199              : } dovar_init;
    7200              : 
    7201              : static bool
    7202         2884 : gfc_nonrect_loop_expr (stmtblock_t *pblock, gfc_se *sep, int loop_n,
    7203              :                        gfc_code *code, gfc_expr *expr, vec<dovar_init> *inits,
    7204              :                        int simple, gfc_expr *curr_loop_var)
    7205              : {
    7206         2884 :   int i;
    7207         4771 :   for (i = 0; i < loop_n; i++)
    7208              :     {
    7209         2441 :       gcc_assert (code->ext.iterator->var->expr_type == EXPR_VARIABLE);
    7210         2441 :       if (gfc_find_sym_in_expr (code->ext.iterator->var->symtree->n.sym, expr))
    7211              :         break;
    7212         1887 :       code = code->block->next;
    7213              :     }
    7214         2884 :   if (i >= loop_n)
    7215              :     return false;
    7216              : 
    7217              :   /* Canonical format: TREE_VEC with [var, multiplier, offset].  */
    7218          554 :   gfc_symbol *var = code->ext.iterator->var->symtree->n.sym;
    7219              : 
    7220          554 :   tree tree_var = NULL_TREE;
    7221          554 :   tree a1 = integer_one_node;
    7222          554 :   tree a2 = integer_zero_node;
    7223              : 
    7224          554 :   if (!simple)
    7225              :     {
    7226              :       /* FIXME: Handle non-const iter steps, cf. PR fortran/110735.  */
    7227            6 :       sorry_at (gfc_get_location (&curr_loop_var->where),
    7228              :                 "non-rectangular loop nest with non-constant step for %qs",
    7229            3 :                 curr_loop_var->symtree->n.sym->name);
    7230            3 :       return false;
    7231              :     }
    7232              : 
    7233              :   dovar_init *di;
    7234              :   unsigned ix;
    7235          551 :   FOR_EACH_VEC_ELT (*inits, ix, di)
    7236           18 :     if (di->sym == var)
    7237              :       {
    7238           18 :         if (!di->non_unit_iter)
    7239              :           {
    7240           16 :             tree_var = di->init;
    7241           16 :             gcc_assert (DECL_P (tree_var));
    7242              :             break;
    7243              :           }
    7244              :         else
    7245              :           {
    7246              :             /* FIXME: Handle non-const iter steps, cf. PR fortran/110735.  */
    7247            2 :             sorry_at (gfc_get_location (&code->loc),
    7248              :                       "non-rectangular loop nest with non-constant step "
    7249              :                       "for %qs", var->name);
    7250            2 :             inform (gfc_get_location (&expr->where), "Used here");
    7251            2 :             return false;
    7252              :           }
    7253              :       }
    7254          533 :   if (tree_var == NULL_TREE)
    7255          533 :     tree_var = var->backend_decl;
    7256              : 
    7257          549 :   if (expr->expr_type == EXPR_VARIABLE)
    7258           54 :     gcc_assert (expr->symtree->n.sym == var);
    7259          495 :   else if (expr->expr_type != EXPR_OP
    7260          495 :            || (expr->value.op.op != INTRINSIC_TIMES
    7261          479 :                && expr->value.op.op != INTRINSIC_PLUS
    7262          359 :                && expr->value.op.op != INTRINSIC_MINUS))
    7263            0 :     gcc_unreachable ();
    7264              :   else
    7265              :     {
    7266          495 :       gfc_se se;
    7267          495 :       gfc_expr *et = NULL, *eo = NULL, *e = expr;
    7268          495 :       if (expr->value.op.op != INTRINSIC_TIMES)
    7269              :         {
    7270          479 :           if (gfc_find_sym_in_expr (var, expr->value.op.op1))
    7271              :             {
    7272          431 :               e = expr->value.op.op1;
    7273          431 :               eo = expr->value.op.op2;
    7274              :             }
    7275              :           else
    7276              :             {
    7277           48 :               eo = expr->value.op.op1;
    7278           48 :               e = expr->value.op.op2;
    7279              :             }
    7280              :         }
    7281          495 :       if (e->value.op.op == INTRINSIC_TIMES)
    7282              :         {
    7283           91 :           if (e->value.op.op1->expr_type == EXPR_VARIABLE
    7284           91 :               && e->value.op.op1->symtree->n.sym == var)
    7285           51 :             et = e->value.op.op2;
    7286              :           else
    7287              :             {
    7288           40 :               et = e->value.op.op1;
    7289           40 :               gcc_assert (e->value.op.op2->expr_type == EXPR_VARIABLE
    7290              :                           && e->value.op.op2->symtree->n.sym == var);
    7291              :             }
    7292              :         }
    7293              :       else
    7294          404 :         gcc_assert (e->expr_type == EXPR_VARIABLE && e->symtree->n.sym == var);
    7295           91 :       if (et != NULL)
    7296              :         {
    7297           91 :           gfc_init_se (&se, NULL);
    7298           91 :           gfc_conv_expr_val (&se, et);
    7299           91 :           gfc_add_block_to_block (pblock, &se.pre);
    7300           91 :           a1 = se.expr;
    7301              :         }
    7302          495 :       if (eo != NULL)
    7303              :         {
    7304          479 :           gfc_init_se (&se, NULL);
    7305          479 :           gfc_conv_expr_val (&se, eo);
    7306          479 :           gfc_add_block_to_block (pblock, &se.pre);
    7307          479 :           a2 = se.expr;
    7308          479 :           if (expr->value.op.op == INTRINSIC_MINUS && expr->value.op.op2 == eo)
    7309              :             /* outer-var - a2.  */
    7310          335 :             a2 = fold_build1 (NEGATE_EXPR, TREE_TYPE (a2), a2);
    7311          144 :           else if (expr->value.op.op == INTRINSIC_MINUS)
    7312              :             /* a2 - outer-var.  */
    7313           24 :             a1 = fold_build1 (NEGATE_EXPR, TREE_TYPE (a1), a1);
    7314              :         }
    7315          495 :       a1 = DECL_P (a1) ? a1 : gfc_evaluate_now (a1, pblock);
    7316          495 :       a2 = DECL_P (a2) ? a2 : gfc_evaluate_now (a2, pblock);
    7317              :     }
    7318              : 
    7319          549 :   gfc_init_se (sep, NULL);
    7320          549 :   sep->expr = make_tree_vec (3);
    7321          549 :   TREE_VEC_ELT (sep->expr, 0) = tree_var;
    7322          549 :   TREE_VEC_ELT (sep->expr, 1) = fold_convert (TREE_TYPE (tree_var), a1);
    7323          549 :   TREE_VEC_ELT (sep->expr, 2) = fold_convert (TREE_TYPE (tree_var), a2);
    7324              : 
    7325          549 :   return true;
    7326              : }
    7327              : 
    7328              : int
    7329          708 : gfc_expr_list_len (gfc_expr_list *list)
    7330              : {
    7331          708 :   unsigned len = 0;
    7332         2092 :   for (; list; list = list->next)
    7333         1384 :     len++;
    7334              : 
    7335          708 :   return len;
    7336              : }
    7337              : 
    7338              : static tree
    7339         9548 : gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock,
    7340              :                   gfc_omp_clauses *do_clauses, tree par_clauses)
    7341              : {
    7342         9548 :   gfc_se se;
    7343         9548 :   tree dovar, stmt, from, to, step, type, init, cond, incr, orig_decls;
    7344         9548 :   tree local_dovar = NULL_TREE, cycle_label, tmp, omp_clauses;
    7345         9548 :   stmtblock_t block;
    7346         9548 :   stmtblock_t body;
    7347         9548 :   gfc_omp_clauses *clauses = code->ext.omp_clauses;
    7348         9548 :   int i, collapse = clauses->collapse;
    7349         9548 :   vec<dovar_init> inits = vNULL;
    7350         9548 :   dovar_init *di;
    7351         9548 :   unsigned ix;
    7352         9548 :   vec<tree, va_heap, vl_embed> *saved_doacross_steps = doacross_steps;
    7353        19096 :   gfc_expr_list *oacc_tile
    7354         9548 :     = do_clauses ? do_clauses->tile_list : clauses->tile_list;
    7355         9548 :   gfc_expr_list *sizes
    7356              :     = do_clauses ? do_clauses->sizes_list : clauses->sizes_list;
    7357         9548 :   gfc_code *orig_code = code;
    7358              : 
    7359              :   /* Both collapsed and tiled loops are lowered the same way.  In
    7360              :      OpenACC, those clauses are not compatible, so prioritize the tile
    7361              :      clause, if present.  */
    7362         9548 :   if (oacc_tile)
    7363           60 :     collapse = gfc_expr_list_len (oacc_tile);
    7364         9488 :   else if (sizes)
    7365          120 :     collapse = gfc_expr_list_len (sizes);
    7366              : 
    7367         9548 :   doacross_steps = NULL;
    7368         9548 :   if (clauses->orderedc)
    7369          134 :     collapse = clauses->orderedc;
    7370         9548 :   if (collapse <= 0)
    7371              :     collapse = 1;
    7372              : 
    7373         9548 :   code = code->block->next;
    7374              : 
    7375         9548 :   init = make_tree_vec (collapse);
    7376         9548 :   cond = make_tree_vec (collapse);
    7377         9548 :   incr = make_tree_vec (collapse);
    7378         9548 :   orig_decls = clauses->ordered ? make_tree_vec (collapse) : NULL_TREE;
    7379              : 
    7380         9548 :   if (pblock == NULL)
    7381              :     {
    7382         6036 :       gfc_start_block (&block);
    7383         6036 :       pblock = &block;
    7384              :     }
    7385              : 
    7386              :   /* simd schedule modifier is only useful for composite do simd and other
    7387              :      constructs including that, where gfc_trans_omp_do is only called
    7388              :      on the simd construct and DO's clauses are translated elsewhere.  */
    7389         9548 :   do_clauses->sched_simd = false;
    7390              : 
    7391         9548 :   omp_clauses = gfc_trans_omp_clauses (pblock, do_clauses, code->loc);
    7392              : 
    7393        21588 :   for (i = 0; i < collapse; i++)
    7394              :     {
    7395        12040 :       int simple = 0;
    7396        12040 :       int dovar_found = 0;
    7397        12040 :       tree dovar_decl;
    7398              : 
    7399        12040 :       if (code->op == EXEC_OMP_TILE || code->op == EXEC_OMP_UNROLL)
    7400              :         {
    7401          320 :           TREE_VEC_ELT (init, i) = NULL_TREE;
    7402          320 :           TREE_VEC_ELT (cond, i) = NULL_TREE;
    7403          320 :           TREE_VEC_ELT (incr, i) = NULL_TREE;
    7404          320 :           TREE_VEC_ELT (incr, i) = NULL_TREE;
    7405          320 :           if (orig_decls)
    7406            2 :             TREE_VEC_ELT (orig_decls, i) = NULL_TREE;
    7407          320 :           continue;
    7408              :         }
    7409        11720 :       gcc_assert (code->op == EXEC_DO);
    7410        11720 :       if (clauses)
    7411              :         {
    7412        11720 :           gfc_omp_namelist *n = NULL;
    7413        11720 :           if (op == EXEC_OMP_SIMD && collapse == 1)
    7414          939 :             for (n = clauses->lists[OMP_LIST_LINEAR];
    7415         1239 :                  n != NULL; n = n->next)
    7416          443 :               if (code->ext.iterator->var->symtree->n.sym == n->sym)
    7417              :                 {
    7418              :                   dovar_found = 3;
    7419              :                   break;
    7420              :                 }
    7421        11720 :           if (n == NULL && op != EXEC_OMP_DISTRIBUTE)
    7422        11483 :             for (n = clauses->lists[OMP_LIST_LASTPRIVATE];
    7423        13544 :                  n != NULL; n = n->next)
    7424         3438 :               if (code->ext.iterator->var->symtree->n.sym == n->sym)
    7425              :                 {
    7426              :                   dovar_found = 2;
    7427              :                   break;
    7428              :                 }
    7429        11720 :           if (n == NULL)
    7430        11456 :             for (n = clauses->lists[OMP_LIST_PRIVATE]; n != NULL; n = n->next)
    7431         6998 :               if (code->ext.iterator->var->symtree->n.sym == n->sym)
    7432              :                 {
    7433              :                   dovar_found = 1;
    7434              :                   break;
    7435              :                 }
    7436              :         }
    7437              : 
    7438              :       /* Evaluate all the expressions in the iterator.  */
    7439        11720 :       gfc_init_se (&se, NULL);
    7440        11720 :       gfc_conv_expr_lhs (&se, code->ext.iterator->var);
    7441        11720 :       gfc_add_block_to_block (pblock, &se.pre);
    7442        11720 :       local_dovar = dovar_decl = dovar = se.expr;
    7443        11720 :       type = TREE_TYPE (dovar);
    7444        11720 :       gcc_assert (TREE_CODE (type) == INTEGER_TYPE);
    7445              : 
    7446        11720 :       gfc_init_se (&se, NULL);
    7447        11720 :       gfc_conv_expr_val (&se, code->ext.iterator->step);
    7448        11720 :       gfc_add_block_to_block (pblock, &se.pre);
    7449        11720 :       step = gfc_evaluate_now (se.expr, pblock);
    7450              : 
    7451        11720 :       if (TREE_CODE (step) == INTEGER_CST)
    7452        11129 :         simple = tree_int_cst_sgn (step);
    7453              : 
    7454        11720 :       gfc_init_se (&se, NULL);
    7455        11720 :       if (!clauses->non_rectangular
    7456        13162 :           || !gfc_nonrect_loop_expr (pblock, &se, i, orig_code->block->next,
    7457              :                                      code->ext.iterator->start, &inits, simple,
    7458         1442 :                                      code->ext.iterator->var))
    7459              :         {
    7460        11404 :           gfc_conv_expr_val (&se, code->ext.iterator->start);
    7461        11404 :           gfc_add_block_to_block (pblock, &se.pre);
    7462        11404 :           if (!DECL_P (se.expr))
    7463        11006 :             se.expr = gfc_evaluate_now (se.expr, pblock);
    7464              :         }
    7465        11720 :       from = se.expr;
    7466              : 
    7467        11720 :       gfc_init_se (&se, NULL);
    7468        11720 :       if (!clauses->non_rectangular
    7469        13162 :           || !gfc_nonrect_loop_expr (pblock, &se, i, orig_code->block->next,
    7470              :                                      code->ext.iterator->end, &inits, simple,
    7471         1442 :                                      code->ext.iterator->var))
    7472              :         {
    7473        11487 :           gfc_conv_expr_val (&se, code->ext.iterator->end);
    7474        11487 :           gfc_add_block_to_block (pblock, &se.pre);
    7475        11487 :           if (!DECL_P (se.expr))
    7476        10252 :             se.expr = gfc_evaluate_now (se.expr, pblock);
    7477              :         }
    7478        11720 :       to = se.expr;
    7479              : 
    7480        11720 :       if (!DECL_P (dovar))
    7481           38 :         dovar_decl
    7482           38 :           = gfc_trans_omp_variable (code->ext.iterator->var->symtree->n.sym,
    7483              :                                     false);
    7484        11720 :       if (simple && !DECL_P (dovar))
    7485              :         {
    7486           38 :           const char *name = code->ext.iterator->var->symtree->n.sym->name;
    7487           38 :           local_dovar = gfc_create_var (type, name);
    7488           38 :           dovar_init e = {code->ext.iterator->var->symtree->n.sym,
    7489           38 :                           dovar, local_dovar, false};
    7490           38 :           inits.safe_push (e);
    7491              :         }
    7492              :       /* Loop body.  */
    7493        11720 :       if (simple)
    7494              :         {
    7495        11129 :           TREE_VEC_ELT (init, i) = build2_v (MODIFY_EXPR, local_dovar, from);
    7496              :           /* The condition should not be folded.  */
    7497        11681 :           TREE_VEC_ELT (cond, i) = build2_loc (input_location, simple > 0
    7498              :                                                ? LE_EXPR : GE_EXPR,
    7499              :                                                logical_type_node, local_dovar,
    7500              :                                                to);
    7501        11129 :           TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location, PLUS_EXPR,
    7502              :                                                     type, local_dovar, step);
    7503        11129 :           TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location,
    7504              :                                                     MODIFY_EXPR,
    7505              :                                                     type, local_dovar,
    7506        11129 :                                                     TREE_VEC_ELT (incr, i));
    7507        11129 :           if (orig_decls && !clauses->orderedc)
    7508              :             orig_decls = NULL;
    7509          383 :           else if (orig_decls)
    7510          383 :             TREE_VEC_ELT (orig_decls, i) = dovar_decl;
    7511              :         }
    7512              :       else
    7513              :         {
    7514              :           /* STEP is not 1 or -1.  Use:
    7515              :              for (count = 0; count < (to + step - from) / step; count++)
    7516              :                {
    7517              :                  dovar = from + count * step;
    7518              :                  body;
    7519              :                cycle_label:;
    7520              :                }  */
    7521          591 :           tmp = fold_build2_loc (input_location, MINUS_EXPR, type, step, from);
    7522          591 :           tmp = fold_build2_loc (input_location, PLUS_EXPR, type, to, tmp);
    7523          591 :           tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, type, tmp,
    7524              :                                  step);
    7525          591 :           tmp = gfc_evaluate_now (tmp, pblock);
    7526          591 :           local_dovar = gfc_create_var (type, "count");
    7527          591 :           TREE_VEC_ELT (init, i) = build2_v (MODIFY_EXPR, local_dovar,
    7528              :                                              build_int_cst (type, 0));
    7529              :           /* The condition should not be folded.  */
    7530          591 :           TREE_VEC_ELT (cond, i) = build2_loc (input_location, LT_EXPR,
    7531              :                                                logical_type_node,
    7532              :                                                local_dovar, tmp);
    7533          591 :           TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location, PLUS_EXPR,
    7534              :                                                     type, local_dovar,
    7535              :                                                     build_int_cst (type, 1));
    7536          591 :           TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location,
    7537              :                                                     MODIFY_EXPR, type,
    7538              :                                                     local_dovar,
    7539          591 :                                                     TREE_VEC_ELT (incr, i));
    7540              : 
    7541              :           /* Initialize DOVAR.  */
    7542          591 :           tmp = fold_build2_loc (input_location, MULT_EXPR, type, local_dovar,
    7543              :                                  step);
    7544          591 :           tmp = fold_build2_loc (input_location, PLUS_EXPR, type, from, tmp);
    7545          591 :           dovar_init e = {code->ext.iterator->var->symtree->n.sym,
    7546          591 :                           dovar, tmp, true};
    7547          591 :           inits.safe_push (e);
    7548          591 :           if (clauses->orderedc)
    7549              :             {
    7550          192 :               if (doacross_steps == NULL)
    7551           47 :                 vec_safe_grow_cleared (doacross_steps, clauses->orderedc, true);
    7552          192 :               (*doacross_steps)[i] = step;
    7553              :             }
    7554          591 :           if (orig_decls)
    7555          198 :             TREE_VEC_ELT (orig_decls, i) = dovar_decl;
    7556              :         }
    7557              : 
    7558        11720 :       if (dovar_found == 3
    7559        11720 :           && op == EXEC_OMP_SIMD
    7560          143 :           && collapse == 1
    7561          143 :           && local_dovar != dovar)
    7562              :         {
    7563          120 :           for (tmp = omp_clauses; tmp; tmp = OMP_CLAUSE_CHAIN (tmp))
    7564          120 :             if (OMP_CLAUSE_CODE (tmp) == OMP_CLAUSE_LINEAR
    7565          120 :                 && OMP_CLAUSE_DECL (tmp) == dovar)
    7566              :               {
    7567           30 :                 OMP_CLAUSE_LINEAR_NO_COPYIN (tmp) = 1;
    7568           30 :                 break;
    7569              :               }
    7570              :         }
    7571        11720 :       if (!dovar_found && op == EXEC_OMP_SIMD)
    7572              :         {
    7573         1359 :           if (collapse == 1)
    7574              :             {
    7575          786 :               tmp = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
    7576          786 :               OMP_CLAUSE_LINEAR_STEP (tmp) = step;
    7577          786 :               OMP_CLAUSE_LINEAR_NO_COPYIN (tmp) = 1;
    7578          786 :               OMP_CLAUSE_DECL (tmp) = dovar_decl;
    7579          786 :               omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
    7580          786 :               if (local_dovar != dovar)
    7581              :                 dovar_found = 3;
    7582              :             }
    7583              :         }
    7584        10361 :       else if (!dovar_found && local_dovar != dovar)
    7585              :         {
    7586          260 :           tmp = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
    7587          260 :           OMP_CLAUSE_DECL (tmp) = dovar_decl;
    7588          260 :           omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
    7589              :         }
    7590        11690 :       if (dovar_found > 1)
    7591              :         {
    7592         1550 :           tree c = NULL;
    7593              : 
    7594         1550 :           tmp = NULL;
    7595         1550 :           if (local_dovar != dovar)
    7596              :             {
    7597              :               /* If dovar is lastprivate, but different counter is used,
    7598              :                  dovar += step needs to be added to
    7599              :                  OMP_CLAUSE_LASTPRIVATE_STMT, otherwise the copied dovar
    7600              :                  will have the value on entry of the last loop, rather
    7601              :                  than value after iterator increment.  */
    7602          243 :               if (clauses->orderedc)
    7603              :                 {
    7604           60 :                   if (clauses->collapse <= 1 || i >= clauses->collapse)
    7605              :                     tmp = local_dovar;
    7606              :                   else
    7607           36 :                     tmp = fold_build2_loc (input_location, PLUS_EXPR,
    7608              :                                            type, local_dovar,
    7609              :                                            build_one_cst (type));
    7610           60 :                   tmp = fold_build2_loc (input_location, MULT_EXPR, type,
    7611              :                                          tmp, step);
    7612           60 :                   tmp = fold_build2_loc (input_location, PLUS_EXPR, type,
    7613              :                                          from, tmp);
    7614              :                 }
    7615              :               else
    7616          183 :                 tmp = fold_build2_loc (input_location, PLUS_EXPR, type,
    7617              :                                        dovar, step);
    7618          243 :               tmp = fold_build2_loc (input_location, MODIFY_EXPR, type,
    7619              :                                      dovar, tmp);
    7620          934 :               for (c = omp_clauses; c ; c = OMP_CLAUSE_CHAIN (c))
    7621          613 :                 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
    7622          613 :                     && OMP_CLAUSE_DECL (c) == dovar_decl)
    7623              :                   {
    7624          105 :                     OMP_CLAUSE_LASTPRIVATE_STMT (c) = tmp;
    7625          105 :                     break;
    7626              :                   }
    7627          508 :                 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
    7628          508 :                          && OMP_CLAUSE_DECL (c) == dovar_decl)
    7629              :                   {
    7630           60 :                     OMP_CLAUSE_LINEAR_STMT (c) = tmp;
    7631           60 :                     break;
    7632              :                   }
    7633              :             }
    7634         1550 :           if (c == NULL && op == EXEC_OMP_DO && par_clauses != NULL)
    7635              :             {
    7636          892 :               for (c = par_clauses; c ; c = OMP_CLAUSE_CHAIN (c))
    7637          892 :                 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
    7638          892 :                     && OMP_CLAUSE_DECL (c) == dovar_decl)
    7639              :                   {
    7640          406 :                     tree l = build_omp_clause (input_location,
    7641              :                                                OMP_CLAUSE_LASTPRIVATE);
    7642          406 :                     if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
    7643            4 :                       OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (l) = 1;
    7644          406 :                     OMP_CLAUSE_DECL (l) = dovar_decl;
    7645          406 :                     OMP_CLAUSE_CHAIN (l) = omp_clauses;
    7646          406 :                     OMP_CLAUSE_LASTPRIVATE_STMT (l) = tmp;
    7647          406 :                     omp_clauses = l;
    7648          406 :                     OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_SHARED);
    7649          406 :                     break;
    7650              :                   }
    7651              :             }
    7652         1550 :           gcc_assert (local_dovar == dovar || c != NULL);
    7653              :         }
    7654        11720 :       if (local_dovar != dovar)
    7655              :         {
    7656          629 :           if (op != EXEC_OMP_SIMD || dovar_found == 1)
    7657          550 :             tmp = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
    7658           79 :           else if (collapse == 1)
    7659              :             {
    7660           60 :               tmp = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
    7661           60 :               OMP_CLAUSE_LINEAR_STEP (tmp) = build_int_cst (type, 1);
    7662           60 :               OMP_CLAUSE_LINEAR_NO_COPYIN (tmp) = 1;
    7663           60 :               OMP_CLAUSE_LINEAR_NO_COPYOUT (tmp) = 1;
    7664              :             }
    7665              :           else
    7666           19 :             tmp = build_omp_clause (input_location, OMP_CLAUSE_LASTPRIVATE);
    7667          629 :           OMP_CLAUSE_DECL (tmp) = local_dovar;
    7668          629 :           omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
    7669              :         }
    7670              : 
    7671        11720 :       if (i + 1 < collapse)
    7672         2464 :         code = code->block->next;
    7673              :     }
    7674              : 
    7675         9548 :   if (pblock != &block)
    7676              :     {
    7677         3512 :       pushlevel ();
    7678         3512 :       gfc_start_block (&block);
    7679              :     }
    7680              : 
    7681         9548 :   gfc_start_block (&body);
    7682              : 
    7683        19725 :   FOR_EACH_VEC_ELT (inits, ix, di)
    7684          629 :     gfc_add_modify (&body, di->var, di->init);
    7685         9548 :   inits.release ();
    7686              : 
    7687              :   /* Cycle statement is implemented with a goto.  Exit statement must not be
    7688              :      present for this loop.  */
    7689         9548 :   cycle_label = gfc_build_label_decl (NULL_TREE);
    7690              : 
    7691              :   /* Put these labels where they can be found later.  */
    7692              : 
    7693         9548 :   code->cycle_label = cycle_label;
    7694         9548 :   code->exit_label = NULL_TREE;
    7695              : 
    7696              :   /* Main loop body.  */
    7697         9548 :   if (clauses->lists[OMP_LIST_REDUCTION_INSCAN])
    7698              :     {
    7699           16 :       gfc_code *code1, *scan, *code2, *tmpcode;
    7700           16 :       code1 = tmpcode = code->block->next;
    7701           16 :       if (tmpcode && tmpcode->op != EXEC_OMP_SCAN)
    7702           18 :         while (tmpcode && tmpcode->next && tmpcode->next->op != EXEC_OMP_SCAN)
    7703              :           tmpcode = tmpcode->next;
    7704           16 :       scan = tmpcode->op == EXEC_OMP_SCAN ? tmpcode : tmpcode->next;
    7705           16 :       if (code1 != scan)
    7706           16 :         tmpcode->next = NULL;
    7707           16 :       code2 = scan->next;
    7708           16 :       gcc_assert (scan->op == EXEC_OMP_SCAN);
    7709           16 :       location_t loc = gfc_get_location (&scan->loc);
    7710              : 
    7711           16 :       tmp = code1 != scan ? gfc_trans_code (code1) : build_empty_stmt (loc);
    7712           16 :       tmp = build2 (OMP_SCAN, void_type_node, tmp, NULL_TREE);
    7713           16 :       SET_EXPR_LOCATION (tmp, loc);
    7714           16 :       gfc_add_expr_to_block (&body, tmp);
    7715           16 :       input_location = loc;
    7716           16 :       tree c = gfc_trans_omp_clauses (&body, scan->ext.omp_clauses, scan->loc);
    7717           16 :       tmp = code2 ? gfc_trans_code (code2) : build_empty_stmt (loc);
    7718           16 :       tmp = build2 (OMP_SCAN, void_type_node, tmp, c);
    7719           16 :       SET_EXPR_LOCATION (tmp, loc);
    7720           16 :       if (code1 != scan)
    7721           16 :         tmpcode->next = scan;
    7722              :     }
    7723         9532 :   else if (code->op == EXEC_OMP_TILE || code->op == EXEC_OMP_UNROLL)
    7724          292 :     tmp = gfc_trans_omp_code (code, true);
    7725              :   else
    7726         9240 :     tmp = gfc_trans_omp_code (code->block->next, true);
    7727         9548 :   gfc_add_expr_to_block (&body, tmp);
    7728              : 
    7729              :   /* Label for cycle statements (if needed).  */
    7730         9548 :   if (TREE_USED (cycle_label))
    7731              :     {
    7732         9548 :       tmp = build1_v (LABEL_EXPR, cycle_label);
    7733         9548 :       gfc_add_expr_to_block (&body, tmp);
    7734              :     }
    7735              : 
    7736              :   /* End of loop body.  */
    7737         9548 :   switch (op)
    7738              :     {
    7739         1458 :     case EXEC_OMP_SIMD: stmt = make_node (OMP_SIMD); break;
    7740         2428 :     case EXEC_OMP_DO: stmt = make_node (OMP_FOR); break;
    7741           80 :     case EXEC_OMP_DISTRIBUTE: stmt = make_node (OMP_DISTRIBUTE); break;
    7742          113 :     case EXEC_OMP_LOOP: stmt = make_node (OMP_LOOP); break;
    7743           94 :     case EXEC_OMP_TASKLOOP: stmt = make_node (OMP_TASKLOOP); break;
    7744         4933 :     case EXEC_OACC_LOOP: stmt = make_node (OACC_LOOP); break;
    7745          120 :     case EXEC_OMP_TILE: stmt = make_node (OMP_TILE); break;
    7746          322 :     case EXEC_OMP_UNROLL: stmt = make_node (OMP_UNROLL); break;
    7747            0 :     default: gcc_unreachable ();
    7748              :     }
    7749              : 
    7750         9548 :   SET_EXPR_LOCATION (stmt, gfc_get_location (&orig_code->loc));
    7751         9548 :   TREE_TYPE (stmt) = void_type_node;
    7752         9548 :   OMP_FOR_BODY (stmt) = gfc_finish_block (&body);
    7753         9548 :   OMP_FOR_CLAUSES (stmt) = omp_clauses;
    7754         9548 :   OMP_FOR_INIT (stmt) = init;
    7755         9548 :   OMP_FOR_COND (stmt) = cond;
    7756         9548 :   OMP_FOR_INCR (stmt) = incr;
    7757         9548 :   if (orig_decls)
    7758          140 :     OMP_FOR_ORIG_DECLS (stmt) = orig_decls;
    7759         9548 :   OMP_FOR_NON_RECTANGULAR (stmt) = clauses->non_rectangular;
    7760         9548 :   gfc_add_expr_to_block (&block, stmt);
    7761              : 
    7762         9548 :   vec_free (doacross_steps);
    7763         9548 :   doacross_steps = saved_doacross_steps;
    7764              : 
    7765         9548 :   return gfc_finish_block (&block);
    7766              : }
    7767              : 
    7768              : /* Translate combined OpenACC 'parallel loop', 'kernels loop', 'serial loop'
    7769              :    construct. */
    7770              : 
    7771              : static tree
    7772         1556 : gfc_trans_oacc_combined_directive (gfc_code *code)
    7773              : {
    7774         1556 :   stmtblock_t block, *pblock = NULL;
    7775         1556 :   gfc_omp_clauses construct_clauses, loop_clauses;
    7776         1556 :   tree stmt, oacc_clauses = NULL_TREE;
    7777         1556 :   enum tree_code construct_code;
    7778         1556 :   location_t loc = input_location;
    7779              : 
    7780         1556 :   switch (code->op)
    7781              :     {
    7782              :       case EXEC_OACC_PARALLEL_LOOP:
    7783              :         construct_code = OACC_PARALLEL;
    7784              :         break;
    7785              :       case EXEC_OACC_KERNELS_LOOP:
    7786              :         construct_code = OACC_KERNELS;
    7787              :         break;
    7788              :       case EXEC_OACC_SERIAL_LOOP:
    7789              :         construct_code = OACC_SERIAL;
    7790              :         break;
    7791            0 :       default:
    7792            0 :         gcc_unreachable ();
    7793              :     }
    7794              : 
    7795         1556 :   gfc_start_block (&block);
    7796              : 
    7797         1556 :   memset (&loop_clauses, 0, sizeof (loop_clauses));
    7798         1556 :   if (code->ext.omp_clauses != NULL)
    7799              :     {
    7800         1556 :       memcpy (&construct_clauses, code->ext.omp_clauses,
    7801              :               sizeof (construct_clauses));
    7802         1556 :       loop_clauses.collapse = construct_clauses.collapse;
    7803         1556 :       loop_clauses.gang = construct_clauses.gang;
    7804         1556 :       loop_clauses.gang_static = construct_clauses.gang_static;
    7805         1556 :       loop_clauses.gang_num_expr = construct_clauses.gang_num_expr;
    7806         1556 :       loop_clauses.gang_static_expr = construct_clauses.gang_static_expr;
    7807         1556 :       loop_clauses.vector = construct_clauses.vector;
    7808         1556 :       loop_clauses.vector_expr = construct_clauses.vector_expr;
    7809         1556 :       loop_clauses.worker = construct_clauses.worker;
    7810         1556 :       loop_clauses.worker_expr = construct_clauses.worker_expr;
    7811         1556 :       loop_clauses.seq = construct_clauses.seq;
    7812         1556 :       loop_clauses.par_auto = construct_clauses.par_auto;
    7813         1556 :       loop_clauses.independent = construct_clauses.independent;
    7814         1556 :       loop_clauses.tile_list = construct_clauses.tile_list;
    7815         1556 :       loop_clauses.lists[OMP_LIST_PRIVATE]
    7816         1556 :         = construct_clauses.lists[OMP_LIST_PRIVATE];
    7817         1556 :       loop_clauses.lists[OMP_LIST_REDUCTION]
    7818         1556 :         = construct_clauses.lists[OMP_LIST_REDUCTION];
    7819         1556 :       construct_clauses.gang = false;
    7820         1556 :       construct_clauses.gang_static = false;
    7821         1556 :       construct_clauses.gang_num_expr = NULL;
    7822         1556 :       construct_clauses.gang_static_expr = NULL;
    7823         1556 :       construct_clauses.vector = false;
    7824         1556 :       construct_clauses.vector_expr = NULL;
    7825         1556 :       construct_clauses.worker = false;
    7826         1556 :       construct_clauses.worker_expr = NULL;
    7827         1556 :       construct_clauses.seq = false;
    7828         1556 :       construct_clauses.par_auto = false;
    7829         1556 :       construct_clauses.independent = false;
    7830         1556 :       construct_clauses.independent = false;
    7831         1556 :       construct_clauses.tile_list = NULL;
    7832         1556 :       construct_clauses.lists[OMP_LIST_PRIVATE] = NULL;
    7833         1556 :       if (construct_code == OACC_KERNELS)
    7834           87 :         construct_clauses.lists[OMP_LIST_REDUCTION] = NULL;
    7835         1556 :       oacc_clauses = gfc_trans_omp_clauses (&block, &construct_clauses,
    7836              :                                             code->loc, false, true);
    7837              :     }
    7838         1556 :   if (!loop_clauses.seq)
    7839              :     pblock = &block;
    7840              :   else
    7841           54 :     pushlevel ();
    7842         1556 :   stmt = gfc_trans_omp_do (code, EXEC_OACC_LOOP, pblock, &loop_clauses, NULL);
    7843         1556 :   protected_set_expr_location (stmt, loc);
    7844         1556 :   if (TREE_CODE (stmt) != BIND_EXPR)
    7845         1556 :     stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
    7846              :   else
    7847            0 :     poplevel (0, 0);
    7848         1556 :   stmt = build2_loc (loc, construct_code, void_type_node, stmt, oacc_clauses);
    7849         1556 :   gfc_add_expr_to_block (&block, stmt);
    7850         1556 :   return gfc_finish_block (&block);
    7851              : }
    7852              : 
    7853              : static tree
    7854          108 : gfc_trans_omp_depobj (gfc_code *code)
    7855              : {
    7856          108 :   stmtblock_t block;
    7857          108 :   gfc_se se;
    7858          108 :   gfc_init_se (&se, NULL);
    7859          108 :   gfc_init_block (&block);
    7860          108 :   gfc_conv_expr (&se, code->ext.omp_clauses->depobj);
    7861          108 :   gcc_assert (se.pre.head == NULL && se.post.head == NULL);
    7862          108 :   tree depobj = se.expr;
    7863          108 :   location_t loc = EXPR_LOCATION (depobj);
    7864          108 :   if (!POINTER_TYPE_P (TREE_TYPE (depobj)))
    7865          108 :     depobj = gfc_build_addr_expr (NULL, depobj);
    7866          108 :   depobj = fold_convert (build_pointer_type_for_mode (ptr_type_node,
    7867              :                                                       TYPE_MODE (ptr_type_node),
    7868              :                                                       true), depobj);
    7869          108 :   gfc_omp_namelist *n = code->ext.omp_clauses->lists[OMP_LIST_DEPEND];
    7870          108 :   if (n)
    7871              :     {
    7872           83 :       tree var;
    7873           83 :       if (!n->sym)  /* omp_all_memory.  */
    7874            3 :         var = null_pointer_node;
    7875           80 :       else if (n->expr && n->expr->ref->u.ar.type != AR_FULL)
    7876              :         {
    7877           18 :           gfc_init_se (&se, NULL);
    7878           18 :           if (n->expr->rank == 0)
    7879              :             {
    7880           18 :               gfc_conv_expr_reference (&se, n->expr);
    7881           18 :               var = se.expr;
    7882              :             }
    7883              :           else
    7884              :             {
    7885            0 :               gfc_conv_expr_descriptor (&se, n->expr);
    7886            0 :               var = gfc_conv_array_data (se.expr);
    7887              :             }
    7888           18 :           gfc_add_block_to_block (&block, &se.pre);
    7889           18 :           gfc_add_block_to_block (&block, &se.post);
    7890           18 :           gcc_assert (POINTER_TYPE_P (TREE_TYPE (var)));
    7891              :         }
    7892              :       else
    7893              :         {
    7894           62 :           var = gfc_get_symbol_decl (n->sym);
    7895           99 :           if (POINTER_TYPE_P (TREE_TYPE (var))
    7896           72 :               && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (var))))
    7897            8 :             var = build_fold_indirect_ref (var);
    7898           62 :           if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (var)))
    7899              :             {
    7900           12 :               var = gfc_conv_descriptor_data_get (var);
    7901           12 :               gcc_assert (POINTER_TYPE_P (TREE_TYPE (var)));
    7902              :             }
    7903           50 :           else if ((n->sym->attr.allocatable || n->sym->attr.pointer)
    7904           13 :                    && n->sym->attr.dummy)
    7905            8 :             var = build_fold_indirect_ref (var);
    7906           67 :           else if (!POINTER_TYPE_P (TREE_TYPE (var))
    7907           44 :                    || (n->sym->ts.f90_type == BT_VOID
    7908           12 :                        && !POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (var)))
    7909            8 :                        && !GFC_ARRAY_TYPE_P (TREE_TYPE (TREE_TYPE (var)))))
    7910              :             {
    7911           29 :               TREE_ADDRESSABLE (var) = 1;
    7912           29 :               var = gfc_build_addr_expr (NULL, var);
    7913              :             }
    7914              :         }
    7915           83 :       depobj = save_expr (depobj);
    7916           83 :       tree r = build_fold_indirect_ref_loc (loc, depobj);
    7917           83 :       gfc_add_expr_to_block (&block,
    7918              :                              build2 (MODIFY_EXPR, void_type_node, r, var));
    7919              :     }
    7920              : 
    7921              :   /* Only one may be set. */
    7922          108 :   gcc_assert (((int)(n != NULL) + (int)(code->ext.omp_clauses->destroy)
    7923              :               + (int)(code->ext.omp_clauses->depobj_update != OMP_DEPEND_UNSET))
    7924              :               == 1);
    7925          108 :   int k = -1; /* omp_clauses->destroy */
    7926          108 :   if (!code->ext.omp_clauses->destroy)
    7927           92 :     switch (code->ext.omp_clauses->depobj_update != OMP_DEPEND_UNSET
    7928           92 :             ? code->ext.omp_clauses->depobj_update : n->u.depend_doacross_op)
    7929              :       {
    7930              :       case OMP_DEPEND_IN: k = GOMP_DEPEND_IN; break;
    7931              :       case OMP_DEPEND_OUT: k = GOMP_DEPEND_OUT; break;
    7932              :       case OMP_DEPEND_INOUT: k = GOMP_DEPEND_INOUT; break;
    7933              :       case OMP_DEPEND_INOUTSET: k = GOMP_DEPEND_INOUTSET; break;
    7934              :       case OMP_DEPEND_MUTEXINOUTSET: k = GOMP_DEPEND_MUTEXINOUTSET; break;
    7935            0 :       default: gcc_unreachable ();
    7936              :       }
    7937          108 :   tree t = build_int_cst (ptr_type_node, k);
    7938          108 :   depobj = build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (depobj), depobj,
    7939          108 :                        TYPE_SIZE_UNIT (ptr_type_node));
    7940          108 :   depobj = build_fold_indirect_ref_loc (loc, depobj);
    7941          108 :   gfc_add_expr_to_block (&block, build2 (MODIFY_EXPR, void_type_node, depobj, t));
    7942              : 
    7943          108 :   return gfc_finish_block (&block);
    7944              : }
    7945              : 
    7946              : /* Callback for walk_tree to find an OMP dispatch call and wrap it into an
    7947              :  * IFN_GOMP_DISPATCH.  */
    7948              : 
    7949              : static tree
    7950         2066 : replace_omp_dispatch_call (tree *tp, int *, void *decls_p)
    7951              : {
    7952         2066 :   tree t = *tp;
    7953         2066 :   tree decls = (tree) decls_p;
    7954         2066 :   tree orig_fn_decl = TREE_PURPOSE (decls);
    7955         2066 :   tree dup_fn_decl = TREE_VALUE (decls);
    7956         2066 :   if (TREE_CODE (t) == CALL_EXPR)
    7957              :     {
    7958          141 :       if (CALL_EXPR_FN (t) == dup_fn_decl)
    7959            1 :         CALL_EXPR_FN (t) = orig_fn_decl;
    7960          140 :       else if (TREE_CODE (CALL_EXPR_FN (t)) == ADDR_EXPR
    7961          140 :                && TREE_OPERAND (CALL_EXPR_FN (t), 0) == dup_fn_decl)
    7962          127 :         TREE_OPERAND (CALL_EXPR_FN (t), 0) = dup_fn_decl;
    7963              :       else
    7964              :         return NULL_TREE;
    7965          128 :       *tp = build_call_expr_internal_loc (input_location, IFN_GOMP_DISPATCH,
    7966          128 :                                           TREE_TYPE (t), 1, t);
    7967          128 :       return *tp;
    7968              :     }
    7969              : 
    7970              :   return NULL_TREE;
    7971              : }
    7972              : 
    7973              : static tree
    7974          128 : gfc_trans_omp_dispatch (gfc_code *code)
    7975              : {
    7976          128 :   stmtblock_t block;
    7977          128 :   gfc_code *next = code->block->next;
    7978              :   // assume ill-formed "function dispatch structured
    7979              :   // block" have already been rejected by resolve_omp_dispatch
    7980          128 :   gcc_assert (next->op == EXEC_CALL || next->op == EXEC_ASSIGN);
    7981              : 
    7982              :   // Make duplicate decl for dispatch function call to make it easy to spot
    7983              :   // after translation
    7984          128 :   gfc_symbol *orig_fn_sym;
    7985          128 :   gfc_expr *call_expr = next->op == EXEC_CALL ? next->expr1 : next->expr2;
    7986          128 :   if (call_expr != NULL) // function
    7987              :     {
    7988           71 :       if (call_expr->value.function.isym != NULL) // dig into convert intrinsics
    7989            4 :         call_expr = call_expr->value.function.actual->expr;
    7990           71 :       gcc_assert (call_expr->expr_type == EXPR_FUNCTION);
    7991           71 :       orig_fn_sym = call_expr->value.function.esym
    7992           71 :                       ? call_expr->value.function.esym
    7993            0 :                       : call_expr->symtree->n.sym;
    7994              :     }
    7995              :   else // subroutine
    7996              :     {
    7997           57 :       orig_fn_sym = next->resolved_sym;
    7998              :     }
    7999          128 :   if (!orig_fn_sym->backend_decl)
    8000           25 :     gfc_get_symbol_decl (orig_fn_sym);
    8001          128 :   gfc_symbol dup_fn_sym = *orig_fn_sym;
    8002          128 :   dup_fn_sym.backend_decl = copy_node (orig_fn_sym->backend_decl);
    8003          128 :   if (call_expr != NULL)
    8004           71 :     call_expr->value.function.esym = &dup_fn_sym;
    8005              :   else
    8006           57 :     next->resolved_sym = &dup_fn_sym;
    8007              : 
    8008          128 :   tree body = gfc_trans_code (next);
    8009              : 
    8010              :   // Walk the tree to find the duplicate decl, wrap IFN call and replace
    8011              :   // dup decl with original
    8012          128 :   tree fn_decls
    8013          128 :     = build_tree_list (orig_fn_sym->backend_decl, dup_fn_sym.backend_decl);
    8014          128 :   tree dispatch_call
    8015          128 :     = walk_tree (&body, replace_omp_dispatch_call, fn_decls, NULL);
    8016          128 :   gcc_assert (dispatch_call != NULL_TREE);
    8017              : 
    8018          128 :   gfc_start_block (&block);
    8019          128 :   tree omp_clauses
    8020          128 :     = gfc_trans_omp_clauses (&block, code->ext.omp_clauses, code->loc);
    8021              : 
    8022              :   // Extract depend clauses and create taskwait
    8023          128 :   tree depend_clauses = NULL_TREE;
    8024          128 :   tree *depend_clauses_ptr = &depend_clauses;
    8025          333 :   for (tree c = omp_clauses; c; c = OMP_CLAUSE_CHAIN (c))
    8026              :     {
    8027          205 :       if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
    8028              :         {
    8029            8 :           *depend_clauses_ptr = c;
    8030            8 :           depend_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
    8031              :         }
    8032              :     }
    8033          128 :   if (depend_clauses != NULL_TREE)
    8034              :     {
    8035            4 :       tree stmt = make_node (OMP_TASK);
    8036            4 :       TREE_TYPE (stmt) = void_node;
    8037            4 :       OMP_TASK_CLAUSES (stmt) = depend_clauses;
    8038            4 :       OMP_TASK_BODY (stmt) = NULL_TREE;
    8039            4 :       SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc));
    8040            4 :       gfc_add_expr_to_block (&block, stmt);
    8041              :     }
    8042              : 
    8043          128 :   tree stmt = make_node (OMP_DISPATCH);
    8044          128 :   SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc));
    8045          128 :   TREE_TYPE (stmt) = void_type_node;
    8046          128 :   OMP_DISPATCH_BODY (stmt) = body;
    8047          128 :   OMP_DISPATCH_CLAUSES (stmt) = omp_clauses;
    8048              : 
    8049          128 :   gfc_add_expr_to_block (&block, stmt);
    8050          128 :   return gfc_finish_block (&block);
    8051              : }
    8052              : 
    8053              : static tree
    8054           29 : gfc_trans_omp_error (gfc_code *code)
    8055              : {
    8056           29 :   stmtblock_t block;
    8057           29 :   gfc_se se;
    8058           29 :   tree len, message;
    8059           29 :   bool fatal = code->ext.omp_clauses->severity == OMP_SEVERITY_FATAL;
    8060           42 :   tree fndecl = builtin_decl_explicit (fatal ? BUILT_IN_GOMP_ERROR
    8061              :                                              : BUILT_IN_GOMP_WARNING);
    8062           29 :   gfc_start_block (&block);
    8063           29 :   gfc_init_se (&se, NULL );
    8064           29 :   if (!code->ext.omp_clauses->message)
    8065              :     {
    8066            3 :       message = null_pointer_node;
    8067            3 :       len = build_int_cst (size_type_node, 0);
    8068              :     }
    8069              :   else
    8070              :     {
    8071           26 :       gfc_conv_expr (&se, code->ext.omp_clauses->message);
    8072           26 :       message = se.expr;
    8073           26 :       if (!POINTER_TYPE_P (TREE_TYPE (message)))
    8074              :         /* To ensure an ARRAY_TYPE is not passed as such.  */
    8075           17 :         message = gfc_build_addr_expr (NULL, message);
    8076           26 :       len = se.string_length;
    8077              :     }
    8078           29 :   gfc_add_block_to_block (&block, &se.pre);
    8079           29 :   gfc_add_expr_to_block (&block, build_call_expr_loc (input_location, fndecl,
    8080              :                                                       2, message, len));
    8081           29 :   gfc_add_block_to_block (&block, &se.post);
    8082           29 :   return gfc_finish_block (&block);
    8083              : }
    8084              : 
    8085              : static tree
    8086           70 : gfc_trans_omp_flush (gfc_code *code)
    8087              : {
    8088           70 :   tree call;
    8089           70 :   if (!code->ext.omp_clauses
    8090            4 :       || code->ext.omp_clauses->memorder == OMP_MEMORDER_UNSET
    8091            4 :       || code->ext.omp_clauses->memorder == OMP_MEMORDER_SEQ_CST)
    8092              :     {
    8093           67 :       call = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
    8094           67 :       call = build_call_expr_loc (input_location, call, 0);
    8095              :     }
    8096              :   else
    8097              :     {
    8098            3 :       enum memmodel mo = MEMMODEL_LAST;
    8099            3 :       switch (code->ext.omp_clauses->memorder)
    8100              :         {
    8101              :         case OMP_MEMORDER_ACQ_REL: mo = MEMMODEL_ACQ_REL; break;
    8102              :         case OMP_MEMORDER_RELEASE: mo = MEMMODEL_RELEASE; break;
    8103              :         case OMP_MEMORDER_ACQUIRE: mo = MEMMODEL_ACQUIRE; break;
    8104            0 :         default: gcc_unreachable (); break;
    8105              :         }
    8106            3 :       call = builtin_decl_explicit (BUILT_IN_ATOMIC_THREAD_FENCE);
    8107            3 :       call = build_call_expr_loc (input_location, call, 1,
    8108            3 :                                   build_int_cst (integer_type_node, mo));
    8109              :     }
    8110           70 :   return call;
    8111              : }
    8112              : 
    8113              : static tree
    8114          116 : gfc_trans_omp_master (gfc_code *code)
    8115              : {
    8116          116 :   tree stmt = gfc_trans_code (code->block->next);
    8117          116 :   if (IS_EMPTY_STMT (stmt))
    8118              :     return stmt;
    8119          110 :   return build1_v (OMP_MASTER, stmt);
    8120              : }
    8121              : 
    8122              : static tree
    8123           55 : gfc_trans_omp_masked (gfc_code *code, gfc_omp_clauses *clauses)
    8124              : {
    8125           55 :   stmtblock_t block;
    8126           55 :   tree body = gfc_trans_code (code->block->next);
    8127           55 :   if (IS_EMPTY_STMT (body))
    8128              :     return body;
    8129           46 :   if (!clauses)
    8130           39 :     clauses = code->ext.omp_clauses;
    8131           46 :   gfc_start_block (&block);
    8132           46 :   tree omp_clauses = gfc_trans_omp_clauses (&block, clauses, code->loc);
    8133           46 :   tree stmt = make_node (OMP_MASKED);
    8134           46 :   SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc));
    8135           46 :   TREE_TYPE (stmt) = void_type_node;
    8136           46 :   OMP_MASKED_BODY (stmt) = body;
    8137           46 :   OMP_MASKED_CLAUSES (stmt) = omp_clauses;
    8138           46 :   gfc_add_expr_to_block (&block, stmt);
    8139           46 :   return gfc_finish_block (&block);
    8140              : }
    8141              : 
    8142              : 
    8143              : static tree
    8144          521 : gfc_trans_omp_ordered (gfc_code *code)
    8145              : {
    8146          521 :   if (!flag_openmp)
    8147              :     {
    8148            5 :       if (!code->ext.omp_clauses->simd)
    8149            3 :         return gfc_trans_code (code->block ? code->block->next : NULL);
    8150            2 :       code->ext.omp_clauses->threads = 0;
    8151              :     }
    8152          518 :   tree omp_clauses = gfc_trans_omp_clauses (NULL, code->ext.omp_clauses,
    8153              :                                             code->loc);
    8154          518 :   return build2_loc (input_location, OMP_ORDERED, void_type_node,
    8155          518 :                      code->block ? gfc_trans_code (code->block->next)
    8156          518 :                      : NULL_TREE, omp_clauses);
    8157              : }
    8158              : 
    8159              : static tree
    8160         1908 : gfc_trans_omp_parallel (gfc_code *code)
    8161              : {
    8162         1908 :   stmtblock_t block;
    8163         1908 :   tree stmt, omp_clauses;
    8164              : 
    8165         1908 :   gfc_start_block (&block);
    8166         1908 :   omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
    8167              :                                        code->loc);
    8168         1908 :   pushlevel ();
    8169         1908 :   stmt = gfc_trans_omp_code (code->block->next, true);
    8170         1908 :   stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
    8171         1908 :   stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
    8172              :                      omp_clauses);
    8173         1908 :   gfc_add_expr_to_block (&block, stmt);
    8174         1908 :   return gfc_finish_block (&block);
    8175              : }
    8176              : 
    8177              : enum
    8178              : {
    8179              :   GFC_OMP_SPLIT_SIMD,
    8180              :   GFC_OMP_SPLIT_DO,
    8181              :   GFC_OMP_SPLIT_PARALLEL,
    8182              :   GFC_OMP_SPLIT_DISTRIBUTE,
    8183              :   GFC_OMP_SPLIT_TEAMS,
    8184              :   GFC_OMP_SPLIT_TARGET,
    8185              :   GFC_OMP_SPLIT_TASKLOOP,
    8186              :   GFC_OMP_SPLIT_MASKED,
    8187              :   GFC_OMP_SPLIT_NUM
    8188              : };
    8189              : 
    8190              : enum
    8191              : {
    8192              :   GFC_OMP_MASK_SIMD = (1 << GFC_OMP_SPLIT_SIMD),
    8193              :   GFC_OMP_MASK_DO = (1 << GFC_OMP_SPLIT_DO),
    8194              :   GFC_OMP_MASK_PARALLEL = (1 << GFC_OMP_SPLIT_PARALLEL),
    8195              :   GFC_OMP_MASK_DISTRIBUTE = (1 << GFC_OMP_SPLIT_DISTRIBUTE),
    8196              :   GFC_OMP_MASK_TEAMS = (1 << GFC_OMP_SPLIT_TEAMS),
    8197              :   GFC_OMP_MASK_TARGET = (1 << GFC_OMP_SPLIT_TARGET),
    8198              :   GFC_OMP_MASK_TASKLOOP = (1 << GFC_OMP_SPLIT_TASKLOOP),
    8199              :   GFC_OMP_MASK_MASKED = (1 << GFC_OMP_SPLIT_MASKED)
    8200              : };
    8201              : 
    8202              : /* If a var is in lastprivate/firstprivate/reduction but not in a
    8203              :    data mapping/sharing clause, add it to 'map(tofrom:' if is_target
    8204              :    and to 'shared' otherwise.  */
    8205              : static void
    8206         2569 : gfc_add_clause_implicitly (gfc_omp_clauses *clauses_out,
    8207              :                            gfc_omp_clauses *clauses_in,
    8208              :                            bool is_target, bool is_parallel_do)
    8209              : {
    8210         2569 :   int clauselist_to_add = is_target ? OMP_LIST_MAP : OMP_LIST_SHARED;
    8211         2569 :   gfc_omp_namelist *tail = NULL;
    8212        15414 :   for (int i = 0; i < 5; ++i)
    8213              :     {
    8214        12845 :       gfc_omp_namelist *n;
    8215        12845 :       switch (i)
    8216              :         {
    8217         2569 :         case 0: n = clauses_in->lists[OMP_LIST_FIRSTPRIVATE]; break;
    8218         2569 :         case 1: n = clauses_in->lists[OMP_LIST_LASTPRIVATE]; break;
    8219         2569 :         case 2: n = clauses_in->lists[OMP_LIST_REDUCTION]; break;
    8220         2569 :         case 3: n = clauses_in->lists[OMP_LIST_REDUCTION_INSCAN]; break;
    8221         2569 :         case 4: n = clauses_in->lists[OMP_LIST_REDUCTION_TASK]; break;
    8222              :         default: gcc_unreachable ();
    8223              :         }
    8224        16190 :       for (; n != NULL; n = n->next)
    8225              :         {
    8226              :           gfc_omp_namelist *n2, **n_firstp = NULL, **n_lastp = NULL;
    8227        20698 :           for (int j = 0; j < 6; ++j)
    8228              :             {
    8229        18227 :               gfc_omp_namelist **n2ref = NULL, *prev2 = NULL;
    8230        18227 :               switch (j)
    8231              :                 {
    8232         3345 :                 case 0:
    8233         3345 :                   n2ref = &clauses_out->lists[clauselist_to_add];
    8234         3345 :                   break;
    8235         3308 :                 case 1:
    8236         3308 :                   n2ref = &clauses_out->lists[OMP_LIST_FIRSTPRIVATE];
    8237         3308 :                   break;
    8238         3308 :                 case 2:
    8239         3308 :                   if (is_target)
    8240          256 :                     n2ref = &clauses_in->lists[OMP_LIST_LASTPRIVATE];
    8241              :                   else
    8242         3052 :                     n2ref = &clauses_out->lists[OMP_LIST_LASTPRIVATE];
    8243              :                   break;
    8244         3308 :                 case 3: n2ref = &clauses_out->lists[OMP_LIST_REDUCTION]; break;
    8245         2479 :                 case 4:
    8246         2479 :                   n2ref = &clauses_out->lists[OMP_LIST_REDUCTION_INSCAN];
    8247         2479 :                   break;
    8248         2479 :                 case 5:
    8249         2479 :                   n2ref = &clauses_out->lists[OMP_LIST_REDUCTION_TASK];
    8250         2479 :                   break;
    8251              :                 default: gcc_unreachable ();
    8252              :                 }
    8253        28501 :               for (n2 = *n2ref; n2 != NULL; prev2 = n2, n2 = n2->next)
    8254        13543 :                 if (n2->sym == n->sym)
    8255              :                   break;
    8256        18227 :               if (n2)
    8257              :                 {
    8258         3269 :                   if (j == 0 /* clauselist_to_add */)
    8259              :                     break;  /* Already present.  */
    8260         3232 :                   if (j == 1 /* OMP_LIST_FIRSTPRIVATE */)
    8261              :                     {
    8262         1128 :                       n_firstp = prev2 ? &prev2->next : n2ref;
    8263         1128 :                       continue;
    8264              :                     }
    8265         2104 :                   if (j == 2 /* OMP_LIST_LASTPRIVATE */)
    8266              :                     {
    8267         1267 :                       n_lastp = prev2 ? &prev2->next : n2ref;
    8268         1267 :                       continue;
    8269              :                     }
    8270              :                   break;
    8271              :                 }
    8272              :             }
    8273         3345 :           if (n_firstp && n_lastp)
    8274              :             {
    8275              :               /* For parallel do, GCC puts firstprivate/lastprivate
    8276              :                  on the parallel.  */
    8277          283 :               if (is_parallel_do)
    8278          280 :                 continue;
    8279            3 :               *n_firstp = (*n_firstp)->next;
    8280            3 :               if (!is_target)
    8281            0 :                 *n_lastp = (*n_lastp)->next;
    8282              :             }
    8283         3062 :           else if (is_target && n_lastp)
    8284              :             ;
    8285         3007 :           else if (n2 || n_firstp || n_lastp)
    8286         2648 :             continue;
    8287          417 :           if (clauses_out->lists[clauselist_to_add]
    8288          305 :               && (clauses_out->lists[clauselist_to_add]
    8289          305 :                   == clauses_in->lists[clauselist_to_add]))
    8290              :             {
    8291              :               gfc_omp_namelist *p = NULL;
    8292          421 :               for (n2 = clauses_in->lists[clauselist_to_add]; n2; n2 = n2->next)
    8293              :                 {
    8294          273 :                   if (p)
    8295              :                     {
    8296          125 :                       p->next = gfc_get_omp_namelist ();
    8297          125 :                       p = p->next;
    8298              :                     }
    8299              :                   else
    8300              :                     {
    8301          148 :                       p = gfc_get_omp_namelist ();
    8302          148 :                       clauses_out->lists[clauselist_to_add] = p;
    8303              :                     }
    8304          273 :                   *p = *n2;
    8305              :                 }
    8306              :             }
    8307          417 :           if (!tail)
    8308              :             {
    8309          288 :               tail = clauses_out->lists[clauselist_to_add];
    8310          413 :               for (; tail && tail->next; tail = tail->next)
    8311              :                 ;
    8312              :             }
    8313          417 :           n2 = gfc_get_omp_namelist ();
    8314          417 :           n2->where = n->where;
    8315          417 :           n2->sym = n->sym;
    8316          417 :           if (is_target)
    8317          120 :             n2->u.map.op = OMP_MAP_TOFROM;
    8318          417 :           if (tail)
    8319              :             {
    8320          305 :               tail->next = n2;
    8321          305 :               tail = n2;
    8322              :             }
    8323              :           else
    8324          112 :             clauses_out->lists[clauselist_to_add] = n2;
    8325              :         }
    8326              :     }
    8327         2569 : }
    8328              : 
    8329              : /* Kind of opposite to above, add firstprivate to CLAUSES_OUT if it is mapped
    8330              :    in CLAUSES_IN's FIRSTPRIVATE list but not its MAP list.  */
    8331              : 
    8332              : static void
    8333          351 : gfc_add_firstprivate_if_unmapped (gfc_omp_clauses *clauses_out,
    8334              :                                   gfc_omp_clauses *clauses_in)
    8335              : {
    8336          351 :   gfc_omp_namelist *n = clauses_in->lists[OMP_LIST_FIRSTPRIVATE];
    8337          351 :   gfc_omp_namelist **tail = NULL;
    8338              : 
    8339          501 :   for (; n != NULL; n = n->next)
    8340              :     {
    8341          150 :       gfc_omp_namelist *n2 = clauses_out->lists[OMP_LIST_MAP];
    8342          192 :       for (; n2 != NULL; n2 = n2->next)
    8343           53 :         if (n->sym == n2->sym)
    8344              :           break;
    8345          150 :       if (n2 == NULL)
    8346              :         {
    8347          139 :           gfc_omp_namelist *dup = gfc_get_omp_namelist ();
    8348          139 :           *dup = *n;
    8349          139 :           dup->next = NULL;
    8350          139 :           if (!tail)
    8351              :             {
    8352           76 :               tail = &clauses_out->lists[OMP_LIST_FIRSTPRIVATE];
    8353           76 :               while (*tail && (*tail)->next)
    8354            0 :                 tail = &(*tail)->next;
    8355              :             }
    8356          139 :           *tail = dup;
    8357          139 :           tail = &(*tail)->next;
    8358              :         }
    8359              :     }
    8360          351 : }
    8361              : 
    8362              : static void
    8363         4473 : gfc_free_split_omp_clauses (gfc_code *code, gfc_omp_clauses *clausesa)
    8364              : {
    8365        40257 :   for (int i = 0; i < GFC_OMP_SPLIT_NUM; ++i)
    8366      1431360 :     for (int j = 0; j < OMP_LIST_NUM; ++j)
    8367      1395576 :       if (clausesa[i].lists[j] && clausesa[i].lists[j] != code->ext.omp_clauses->lists[j])
    8368         1399 :         for (gfc_omp_namelist *n = clausesa[i].lists[j]; n;)
    8369              :           {
    8370          957 :             gfc_omp_namelist *p = n;
    8371          957 :             n = n->next;
    8372          957 :             free (p);
    8373              :           }
    8374         4473 : }
    8375              : 
    8376              : static void
    8377         4473 : gfc_split_omp_clauses (gfc_code *code,
    8378              :                        gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM])
    8379              : {
    8380         4473 :   int mask = 0, innermost = 0;
    8381         4473 :   bool is_loop = false;
    8382         4473 :   memset (clausesa, 0, GFC_OMP_SPLIT_NUM * sizeof (gfc_omp_clauses));
    8383         4473 :   switch (code->op)
    8384              :     {
    8385              :     case EXEC_OMP_DISTRIBUTE:
    8386              :       innermost = GFC_OMP_SPLIT_DISTRIBUTE;
    8387              :       break;
    8388           38 :     case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
    8389           38 :       mask = GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
    8390           38 :       innermost = GFC_OMP_SPLIT_DO;
    8391           38 :       break;
    8392           28 :     case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
    8393           28 :       mask = GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_PARALLEL
    8394              :              | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
    8395           28 :       innermost = GFC_OMP_SPLIT_SIMD;
    8396           28 :       break;
    8397           47 :     case EXEC_OMP_DISTRIBUTE_SIMD:
    8398           47 :       mask = GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_SIMD;
    8399           47 :       innermost = GFC_OMP_SPLIT_SIMD;
    8400           47 :       break;
    8401            0 :     case EXEC_OMP_DO:
    8402            0 :     case EXEC_OMP_LOOP:
    8403            0 :       innermost = GFC_OMP_SPLIT_DO;
    8404            0 :       break;
    8405          126 :     case EXEC_OMP_DO_SIMD:
    8406          126 :       mask = GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
    8407          126 :       innermost = GFC_OMP_SPLIT_SIMD;
    8408          126 :       break;
    8409            0 :     case EXEC_OMP_PARALLEL:
    8410            0 :       innermost = GFC_OMP_SPLIT_PARALLEL;
    8411            0 :       break;
    8412         1116 :     case EXEC_OMP_PARALLEL_DO:
    8413         1116 :     case EXEC_OMP_PARALLEL_LOOP:
    8414         1116 :       mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
    8415         1116 :       innermost = GFC_OMP_SPLIT_DO;
    8416         1116 :       break;
    8417          285 :     case EXEC_OMP_PARALLEL_DO_SIMD:
    8418          285 :       mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
    8419          285 :       innermost = GFC_OMP_SPLIT_SIMD;
    8420          285 :       break;
    8421           11 :     case EXEC_OMP_PARALLEL_MASKED:
    8422           11 :       mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_MASKED;
    8423           11 :       innermost = GFC_OMP_SPLIT_MASKED;
    8424           11 :       break;
    8425           14 :     case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
    8426           14 :       mask = (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_MASKED
    8427              :               | GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD);
    8428           14 :       innermost = GFC_OMP_SPLIT_TASKLOOP;
    8429           14 :       break;
    8430           20 :     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
    8431           20 :       mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD;
    8432           20 :       innermost = GFC_OMP_SPLIT_TASKLOOP;
    8433           20 :       break;
    8434           24 :     case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
    8435           24 :       mask = (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_MASKED
    8436              :               | GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD);
    8437           24 :       innermost = GFC_OMP_SPLIT_SIMD;
    8438           24 :       break;
    8439           28 :     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
    8440           28 :       mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD;
    8441           28 :       innermost = GFC_OMP_SPLIT_SIMD;
    8442           28 :       break;
    8443            0 :     case EXEC_OMP_SIMD:
    8444            0 :       innermost = GFC_OMP_SPLIT_SIMD;
    8445            0 :       break;
    8446         2018 :     case EXEC_OMP_TARGET:
    8447         2018 :       innermost = GFC_OMP_SPLIT_TARGET;
    8448         2018 :       break;
    8449           23 :     case EXEC_OMP_TARGET_PARALLEL:
    8450           23 :       mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_PARALLEL;
    8451           23 :       innermost = GFC_OMP_SPLIT_PARALLEL;
    8452           23 :       break;
    8453           80 :     case EXEC_OMP_TARGET_PARALLEL_DO:
    8454           80 :     case EXEC_OMP_TARGET_PARALLEL_LOOP:
    8455           80 :       mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
    8456           80 :       innermost = GFC_OMP_SPLIT_DO;
    8457           80 :       break;
    8458           16 :     case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
    8459           16 :       mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO
    8460              :              | GFC_OMP_MASK_SIMD;
    8461           16 :       innermost = GFC_OMP_SPLIT_SIMD;
    8462           16 :       break;
    8463           26 :     case EXEC_OMP_TARGET_SIMD:
    8464           26 :       mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_SIMD;
    8465           26 :       innermost = GFC_OMP_SPLIT_SIMD;
    8466           26 :       break;
    8467           73 :     case EXEC_OMP_TARGET_TEAMS:
    8468           73 :       mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS;
    8469           73 :       innermost = GFC_OMP_SPLIT_TEAMS;
    8470           73 :       break;
    8471           14 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
    8472           14 :       mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS
    8473              :              | GFC_OMP_MASK_DISTRIBUTE;
    8474           14 :       innermost = GFC_OMP_SPLIT_DISTRIBUTE;
    8475           14 :       break;
    8476           60 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
    8477           60 :       mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
    8478              :              | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
    8479           60 :       innermost = GFC_OMP_SPLIT_DO;
    8480           60 :       break;
    8481           30 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
    8482           30 :       mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
    8483              :              | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
    8484           30 :       innermost = GFC_OMP_SPLIT_SIMD;
    8485           30 :       break;
    8486           16 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
    8487           16 :       mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS
    8488              :              | GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_SIMD;
    8489           16 :       innermost = GFC_OMP_SPLIT_SIMD;
    8490           16 :       break;
    8491           13 :     case EXEC_OMP_TARGET_TEAMS_LOOP:
    8492           13 :       mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DO;
    8493           13 :       innermost = GFC_OMP_SPLIT_DO;
    8494           13 :       break;
    8495            8 :     case EXEC_OMP_MASKED_TASKLOOP:
    8496            8 :       mask = GFC_OMP_MASK_MASKED | GFC_OMP_MASK_TASKLOOP;
    8497            8 :       innermost = GFC_OMP_SPLIT_TASKLOOP;
    8498            8 :       break;
    8499            0 :     case EXEC_OMP_MASTER_TASKLOOP:
    8500            0 :     case EXEC_OMP_TASKLOOP:
    8501            0 :       innermost = GFC_OMP_SPLIT_TASKLOOP;
    8502            0 :       break;
    8503           24 :     case EXEC_OMP_MASKED_TASKLOOP_SIMD:
    8504           24 :       mask = GFC_OMP_MASK_MASKED | GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD;
    8505           24 :       innermost = GFC_OMP_SPLIT_SIMD;
    8506           24 :       break;
    8507           45 :     case EXEC_OMP_MASTER_TASKLOOP_SIMD:
    8508           45 :     case EXEC_OMP_TASKLOOP_SIMD:
    8509           45 :       mask = GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD;
    8510           45 :       innermost = GFC_OMP_SPLIT_SIMD;
    8511           45 :       break;
    8512          142 :     case EXEC_OMP_TEAMS:
    8513          142 :       innermost = GFC_OMP_SPLIT_TEAMS;
    8514          142 :       break;
    8515           14 :     case EXEC_OMP_TEAMS_DISTRIBUTE:
    8516           14 :       mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE;
    8517           14 :       innermost = GFC_OMP_SPLIT_DISTRIBUTE;
    8518           14 :       break;
    8519           34 :     case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
    8520           34 :       mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
    8521              :              | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
    8522           34 :       innermost = GFC_OMP_SPLIT_DO;
    8523           34 :       break;
    8524           57 :     case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
    8525           57 :       mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
    8526              :              | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
    8527           57 :       innermost = GFC_OMP_SPLIT_SIMD;
    8528           57 :       break;
    8529           37 :     case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
    8530           37 :       mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_SIMD;
    8531           37 :       innermost = GFC_OMP_SPLIT_SIMD;
    8532           37 :       break;
    8533              :     case EXEC_OMP_TEAMS_LOOP:
    8534              :       mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DO;
    8535              :       innermost = GFC_OMP_SPLIT_DO;
    8536              :       break;
    8537            0 :     default:
    8538            0 :       gcc_unreachable ();
    8539              :     }
    8540         4467 :   if (mask == 0)
    8541              :     {
    8542         2160 :       clausesa[innermost] = *code->ext.omp_clauses;
    8543         2160 :       return;
    8544              :     }
    8545              :   /* Loops are similar to DO but still a bit different.  */
    8546         2313 :   switch (code->op)
    8547              :     {
    8548           54 :     case EXEC_OMP_LOOP:
    8549           54 :     case EXEC_OMP_PARALLEL_LOOP:
    8550           54 :     case EXEC_OMP_TEAMS_LOOP:
    8551           54 :     case EXEC_OMP_TARGET_PARALLEL_LOOP:
    8552           54 :     case EXEC_OMP_TARGET_TEAMS_LOOP:
    8553           54 :       is_loop = true;
    8554         2313 :     default:
    8555         2313 :       break;
    8556              :     }
    8557         2313 :   if (code->ext.omp_clauses != NULL)
    8558              :     {
    8559         2313 :       if (mask & GFC_OMP_MASK_TARGET)
    8560              :         {
    8561              :           /* First the clauses that are unique to some constructs.  */
    8562          351 :           clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_MAP]
    8563          351 :             = code->ext.omp_clauses->lists[OMP_LIST_MAP];
    8564          351 :           clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_IS_DEVICE_PTR]
    8565          351 :             = code->ext.omp_clauses->lists[OMP_LIST_IS_DEVICE_PTR];
    8566          351 :           clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_HAS_DEVICE_ADDR]
    8567          351 :             = code->ext.omp_clauses->lists[OMP_LIST_HAS_DEVICE_ADDR];
    8568          351 :           clausesa[GFC_OMP_SPLIT_TARGET].device
    8569          351 :             = code->ext.omp_clauses->device;
    8570          351 :           clausesa[GFC_OMP_SPLIT_TARGET].thread_limit_list
    8571          351 :             = code->ext.omp_clauses->thread_limit_list;
    8572          351 :           clausesa[GFC_OMP_SPLIT_TARGET].thread_limit_strict
    8573          351 :             = code->ext.omp_clauses->thread_limit_strict;
    8574          351 :           clausesa[GFC_OMP_SPLIT_TARGET].thread_limit_dims
    8575          351 :             = code->ext.omp_clauses->thread_limit_dims;
    8576          351 :           clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_USES_ALLOCATORS]
    8577          351 :             = code->ext.omp_clauses->lists[OMP_LIST_USES_ALLOCATORS];
    8578         2457 :           for (int i = 0; i < OMP_DEFAULTMAP_CAT_NUM; i++)
    8579         2106 :             clausesa[GFC_OMP_SPLIT_TARGET].defaultmap[i]
    8580         2106 :               = code->ext.omp_clauses->defaultmap[i];
    8581          351 :           clausesa[GFC_OMP_SPLIT_TARGET].if_exprs[OMP_IF_TARGET]
    8582          351 :             = code->ext.omp_clauses->if_exprs[OMP_IF_TARGET];
    8583              :           /* And this is copied to all.  */
    8584          351 :           clausesa[GFC_OMP_SPLIT_TARGET].if_expr
    8585          351 :             = code->ext.omp_clauses->if_expr;
    8586          351 :           clausesa[GFC_OMP_SPLIT_TARGET].nowait
    8587          351 :             = code->ext.omp_clauses->nowait;
    8588          351 :           clausesa[GFC_OMP_SPLIT_TARGET].device_type
    8589          351 :             = code->ext.omp_clauses->device_type;
    8590          351 :           clausesa[GFC_OMP_SPLIT_TARGET].message
    8591          351 :             = code->ext.omp_clauses->message;
    8592          351 :           clausesa[GFC_OMP_SPLIT_TARGET].severity
    8593          351 :             = code->ext.omp_clauses->severity;
    8594              :         }
    8595         2313 :       if (mask & GFC_OMP_MASK_TEAMS)
    8596              :         {
    8597              :           /* First the clauses that are unique to some constructs.  */
    8598          354 :           clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_list
    8599          354 :             = code->ext.omp_clauses->num_teams_list;
    8600          354 :           clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_dims
    8601          354 :             = code->ext.omp_clauses->num_teams_dims;
    8602          354 :           clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit_list
    8603          354 :             = code->ext.omp_clauses->thread_limit_list;
    8604          354 :           clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit_strict
    8605          354 :             = code->ext.omp_clauses->thread_limit_strict;
    8606          354 :           clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit_dims
    8607          354 :             = code->ext.omp_clauses->thread_limit_dims;
    8608              :           /* Shared and default clauses are allowed on parallel, teams
    8609              :              and taskloop.  */
    8610          354 :           clausesa[GFC_OMP_SPLIT_TEAMS].lists[OMP_LIST_SHARED]
    8611          354 :             = code->ext.omp_clauses->lists[OMP_LIST_SHARED];
    8612          354 :           clausesa[GFC_OMP_SPLIT_TEAMS].default_sharing
    8613          354 :             = code->ext.omp_clauses->default_sharing;
    8614              :           /* Message is used on target, teams, and parallel.  */
    8615          354 :           clausesa[GFC_OMP_SPLIT_TEAMS].message
    8616          354 :             = code->ext.omp_clauses->message;
    8617          354 :           clausesa[GFC_OMP_SPLIT_TEAMS].severity
    8618          354 :             = code->ext.omp_clauses->severity;
    8619              :         }
    8620         2313 :       if (mask & GFC_OMP_MASK_DISTRIBUTE)
    8621              :         {
    8622              :           /* First the clauses that are unique to some constructs.  */
    8623          375 :           clausesa[GFC_OMP_SPLIT_DISTRIBUTE].dist_sched_kind
    8624          375 :             = code->ext.omp_clauses->dist_sched_kind;
    8625          375 :           clausesa[GFC_OMP_SPLIT_DISTRIBUTE].dist_chunk_size
    8626          375 :             = code->ext.omp_clauses->dist_chunk_size;
    8627              :           /* Duplicate collapse.  */
    8628          375 :           clausesa[GFC_OMP_SPLIT_DISTRIBUTE].collapse
    8629          375 :             = code->ext.omp_clauses->collapse;
    8630          375 :           clausesa[GFC_OMP_SPLIT_DISTRIBUTE].order_concurrent
    8631          375 :             = code->ext.omp_clauses->order_concurrent;
    8632          375 :           clausesa[GFC_OMP_SPLIT_DISTRIBUTE].order_unconstrained
    8633          375 :             = code->ext.omp_clauses->order_unconstrained;
    8634          375 :           clausesa[GFC_OMP_SPLIT_DISTRIBUTE].order_reproducible
    8635          375 :             = code->ext.omp_clauses->order_reproducible;
    8636              :         }
    8637         2313 :       if (mask & GFC_OMP_MASK_PARALLEL)
    8638              :         {
    8639              :           /* First the clauses that are unique to some constructs.  */
    8640         1864 :           clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_COPYIN]
    8641         1864 :             = code->ext.omp_clauses->lists[OMP_LIST_COPYIN];
    8642         1864 :           clausesa[GFC_OMP_SPLIT_PARALLEL].num_threads_list
    8643         1864 :             = code->ext.omp_clauses->num_threads_list;
    8644         1864 :           clausesa[GFC_OMP_SPLIT_PARALLEL].num_threads_strict
    8645         1864 :             = code->ext.omp_clauses->num_threads_strict;
    8646         1864 :           clausesa[GFC_OMP_SPLIT_PARALLEL].num_threads_dims
    8647         1864 :             = code->ext.omp_clauses->num_threads_dims;
    8648         1864 :           clausesa[GFC_OMP_SPLIT_PARALLEL].proc_bind
    8649         1864 :             = code->ext.omp_clauses->proc_bind;
    8650              :           /* Shared and default clauses are allowed on parallel, teams
    8651              :              and taskloop.  */
    8652         1864 :           clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_SHARED]
    8653         1864 :             = code->ext.omp_clauses->lists[OMP_LIST_SHARED];
    8654         1864 :           clausesa[GFC_OMP_SPLIT_PARALLEL].default_sharing
    8655         1864 :             = code->ext.omp_clauses->default_sharing;
    8656         1864 :           clausesa[GFC_OMP_SPLIT_PARALLEL].if_exprs[OMP_IF_PARALLEL]
    8657         1864 :             = code->ext.omp_clauses->if_exprs[OMP_IF_PARALLEL];
    8658              :           /* And this is copied to all.  */
    8659         1864 :           clausesa[GFC_OMP_SPLIT_PARALLEL].if_expr
    8660         1864 :             = code->ext.omp_clauses->if_expr;
    8661         1864 :           clausesa[GFC_OMP_SPLIT_PARALLEL].message
    8662         1864 :             = code->ext.omp_clauses->message;
    8663         1864 :           clausesa[GFC_OMP_SPLIT_PARALLEL].severity
    8664         1864 :             = code->ext.omp_clauses->severity;
    8665              :         }
    8666         2313 :       if (mask & GFC_OMP_MASK_MASKED)
    8667           81 :         clausesa[GFC_OMP_SPLIT_MASKED].filter = code->ext.omp_clauses->filter;
    8668         2313 :       if ((mask & GFC_OMP_MASK_DO) && !is_loop)
    8669              :         {
    8670              :           /* First the clauses that are unique to some constructs.  */
    8671         1835 :           clausesa[GFC_OMP_SPLIT_DO].ordered
    8672         1835 :             = code->ext.omp_clauses->ordered;
    8673         1835 :           clausesa[GFC_OMP_SPLIT_DO].orderedc
    8674         1835 :             = code->ext.omp_clauses->orderedc;
    8675         1835 :           clausesa[GFC_OMP_SPLIT_DO].sched_kind
    8676         1835 :             = code->ext.omp_clauses->sched_kind;
    8677         1835 :           if (innermost == GFC_OMP_SPLIT_SIMD)
    8678          542 :             clausesa[GFC_OMP_SPLIT_DO].sched_simd
    8679          542 :               = code->ext.omp_clauses->sched_simd;
    8680         1835 :           clausesa[GFC_OMP_SPLIT_DO].sched_monotonic
    8681         1835 :             = code->ext.omp_clauses->sched_monotonic;
    8682         1835 :           clausesa[GFC_OMP_SPLIT_DO].sched_nonmonotonic
    8683         1835 :             = code->ext.omp_clauses->sched_nonmonotonic;
    8684         1835 :           clausesa[GFC_OMP_SPLIT_DO].chunk_size
    8685         1835 :             = code->ext.omp_clauses->chunk_size;
    8686         1835 :           clausesa[GFC_OMP_SPLIT_DO].nowait
    8687         1835 :             = code->ext.omp_clauses->nowait;
    8688              :         }
    8689         1889 :       if (mask & GFC_OMP_MASK_DO)
    8690              :         {
    8691         1889 :           clausesa[GFC_OMP_SPLIT_DO].bind
    8692         1889 :             = code->ext.omp_clauses->bind;
    8693              :           /* Duplicate collapse.  */
    8694         1889 :           clausesa[GFC_OMP_SPLIT_DO].collapse
    8695         1889 :             = code->ext.omp_clauses->collapse;
    8696         1889 :           clausesa[GFC_OMP_SPLIT_DO].order_concurrent
    8697         1889 :             = code->ext.omp_clauses->order_concurrent;
    8698         1889 :           clausesa[GFC_OMP_SPLIT_DO].order_unconstrained
    8699         1889 :             = code->ext.omp_clauses->order_unconstrained;
    8700         1889 :           clausesa[GFC_OMP_SPLIT_DO].order_reproducible
    8701         1889 :             = code->ext.omp_clauses->order_reproducible;
    8702              :         }
    8703         2313 :       if (mask & GFC_OMP_MASK_SIMD)
    8704              :         {
    8705          823 :           clausesa[GFC_OMP_SPLIT_SIMD].safelen_expr
    8706          823 :             = code->ext.omp_clauses->safelen_expr;
    8707          823 :           clausesa[GFC_OMP_SPLIT_SIMD].simdlen_expr
    8708          823 :             = code->ext.omp_clauses->simdlen_expr;
    8709          823 :           clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_ALIGNED]
    8710          823 :             = code->ext.omp_clauses->lists[OMP_LIST_ALIGNED];
    8711              :           /* Duplicate collapse.  */
    8712          823 :           clausesa[GFC_OMP_SPLIT_SIMD].collapse
    8713          823 :             = code->ext.omp_clauses->collapse;
    8714          823 :           clausesa[GFC_OMP_SPLIT_SIMD].if_exprs[OMP_IF_SIMD]
    8715          823 :             = code->ext.omp_clauses->if_exprs[OMP_IF_SIMD];
    8716          823 :           clausesa[GFC_OMP_SPLIT_SIMD].order_concurrent
    8717          823 :             = code->ext.omp_clauses->order_concurrent;
    8718          823 :           clausesa[GFC_OMP_SPLIT_SIMD].order_unconstrained
    8719          823 :             = code->ext.omp_clauses->order_unconstrained;
    8720          823 :           clausesa[GFC_OMP_SPLIT_SIMD].order_reproducible
    8721          823 :             = code->ext.omp_clauses->order_reproducible;
    8722              :           /* And this is copied to all.  */
    8723          823 :           clausesa[GFC_OMP_SPLIT_SIMD].if_expr
    8724          823 :             = code->ext.omp_clauses->if_expr;
    8725              :         }
    8726         2313 :       if (mask & GFC_OMP_MASK_TASKLOOP)
    8727              :         {
    8728              :           /* First the clauses that are unique to some constructs.  */
    8729          163 :           clausesa[GFC_OMP_SPLIT_TASKLOOP].nogroup
    8730          163 :             = code->ext.omp_clauses->nogroup;
    8731          163 :           clausesa[GFC_OMP_SPLIT_TASKLOOP].grainsize
    8732          163 :             = code->ext.omp_clauses->grainsize;
    8733          163 :           clausesa[GFC_OMP_SPLIT_TASKLOOP].grainsize_strict
    8734          163 :             = code->ext.omp_clauses->grainsize_strict;
    8735          163 :           clausesa[GFC_OMP_SPLIT_TASKLOOP].num_tasks
    8736          163 :             = code->ext.omp_clauses->num_tasks;
    8737          163 :           clausesa[GFC_OMP_SPLIT_TASKLOOP].num_tasks_strict
    8738          163 :             = code->ext.omp_clauses->num_tasks_strict;
    8739          163 :           clausesa[GFC_OMP_SPLIT_TASKLOOP].priority
    8740          163 :             = code->ext.omp_clauses->priority;
    8741          163 :           clausesa[GFC_OMP_SPLIT_TASKLOOP].final_expr
    8742          163 :             = code->ext.omp_clauses->final_expr;
    8743          163 :           clausesa[GFC_OMP_SPLIT_TASKLOOP].untied
    8744          163 :             = code->ext.omp_clauses->untied;
    8745          163 :           clausesa[GFC_OMP_SPLIT_TASKLOOP].mergeable
    8746          163 :             = code->ext.omp_clauses->mergeable;
    8747          163 :           clausesa[GFC_OMP_SPLIT_TASKLOOP].if_exprs[OMP_IF_TASKLOOP]
    8748          163 :             = code->ext.omp_clauses->if_exprs[OMP_IF_TASKLOOP];
    8749              :           /* And this is copied to all.  */
    8750          163 :           clausesa[GFC_OMP_SPLIT_TASKLOOP].if_expr
    8751          163 :             = code->ext.omp_clauses->if_expr;
    8752              :           /* Shared and default clauses are allowed on parallel, teams
    8753              :              and taskloop.  */
    8754          163 :           clausesa[GFC_OMP_SPLIT_TASKLOOP].lists[OMP_LIST_SHARED]
    8755          163 :             = code->ext.omp_clauses->lists[OMP_LIST_SHARED];
    8756          163 :           clausesa[GFC_OMP_SPLIT_TASKLOOP].default_sharing
    8757          163 :             = code->ext.omp_clauses->default_sharing;
    8758              :           /* Duplicate collapse.  */
    8759          163 :           clausesa[GFC_OMP_SPLIT_TASKLOOP].collapse
    8760          163 :             = code->ext.omp_clauses->collapse;
    8761              :         }
    8762              :       /* Private clause is supported on all constructs but master/masked,
    8763              :          it is enough to put it on the innermost one except for master/masked.  For
    8764              :          !$ omp parallel do put it on parallel though,
    8765              :          as that's what we did for OpenMP 3.1.  */
    8766         2313 :       clausesa[((innermost == GFC_OMP_SPLIT_DO && !is_loop)
    8767              :                 || code->op == EXEC_OMP_PARALLEL_MASTER
    8768         1020 :                 || code->op == EXEC_OMP_PARALLEL_MASKED)
    8769         1009 :                ? (int) GFC_OMP_SPLIT_PARALLEL
    8770         3322 :                : innermost].lists[OMP_LIST_PRIVATE]
    8771         2313 :         = code->ext.omp_clauses->lists[OMP_LIST_PRIVATE];
    8772              :       /* Firstprivate clause is supported on all constructs but
    8773              :          simd and masked/master.  Put it on the outermost of those and duplicate
    8774              :          on parallel and teams.  */
    8775         2313 :       if (mask & GFC_OMP_MASK_TARGET)
    8776          351 :         gfc_add_firstprivate_if_unmapped (&clausesa[GFC_OMP_SPLIT_TARGET],
    8777              :                                           code->ext.omp_clauses);
    8778         2313 :       if (mask & GFC_OMP_MASK_TEAMS)
    8779          354 :         clausesa[GFC_OMP_SPLIT_TEAMS].lists[OMP_LIST_FIRSTPRIVATE]
    8780          354 :           = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
    8781         1959 :       else if (mask & GFC_OMP_MASK_DISTRIBUTE)
    8782          113 :         clausesa[GFC_OMP_SPLIT_DISTRIBUTE].lists[OMP_LIST_FIRSTPRIVATE]
    8783          113 :           = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
    8784         2313 :       if (mask & GFC_OMP_MASK_TASKLOOP)
    8785          163 :         clausesa[GFC_OMP_SPLIT_TASKLOOP].lists[OMP_LIST_FIRSTPRIVATE]
    8786          163 :           = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
    8787         2313 :       if ((mask & GFC_OMP_MASK_PARALLEL)
    8788         1864 :           && !(mask & GFC_OMP_MASK_TASKLOOP))
    8789         1778 :         clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_FIRSTPRIVATE]
    8790         1778 :           = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
    8791          535 :       else if ((mask & GFC_OMP_MASK_DO) && !is_loop)
    8792          126 :         clausesa[GFC_OMP_SPLIT_DO].lists[OMP_LIST_FIRSTPRIVATE]
    8793          126 :           = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
    8794              :       /* Lastprivate is allowed on distribute, do, simd, taskloop and loop.
    8795              :          In parallel do{, simd} we actually want to put it on
    8796              :          parallel rather than do.  */
    8797         2313 :       if (mask & GFC_OMP_MASK_DISTRIBUTE)
    8798          375 :         clausesa[GFC_OMP_SPLIT_DISTRIBUTE].lists[OMP_LIST_LASTPRIVATE]
    8799          375 :           = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
    8800         2313 :       if (mask & GFC_OMP_MASK_TASKLOOP)
    8801          163 :         clausesa[GFC_OMP_SPLIT_TASKLOOP].lists[OMP_LIST_LASTPRIVATE]
    8802          163 :           = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
    8803         2313 :       if ((mask & GFC_OMP_MASK_PARALLEL) && !is_loop
    8804         1829 :           && !(mask & GFC_OMP_MASK_TASKLOOP))
    8805         1743 :         clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_LASTPRIVATE]
    8806         1743 :           = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
    8807          570 :       else if (mask & GFC_OMP_MASK_DO)
    8808          180 :         clausesa[GFC_OMP_SPLIT_DO].lists[OMP_LIST_LASTPRIVATE]
    8809          180 :           = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
    8810         2313 :       if (mask & GFC_OMP_MASK_SIMD)
    8811          823 :         clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_LASTPRIVATE]
    8812          823 :           = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
    8813              :       /* Reduction is allowed on simd, do, parallel, teams, taskloop, and loop.
    8814              :          Duplicate it on all of them, but
    8815              :          - omit on do if parallel is present;
    8816              :          - omit on task and parallel if loop is present;
    8817              :          additionally, inscan applies to do/simd only.  */
    8818         9252 :       for (int i = OMP_LIST_REDUCTION; i <= OMP_LIST_REDUCTION_TASK; i++)
    8819              :         {
    8820         6939 :           if (mask & GFC_OMP_MASK_TASKLOOP
    8821          489 :               && i != OMP_LIST_REDUCTION_INSCAN)
    8822          326 :             clausesa[GFC_OMP_SPLIT_TASKLOOP].lists[i]
    8823          326 :               = code->ext.omp_clauses->lists[i];
    8824         6939 :           if (mask & GFC_OMP_MASK_TEAMS
    8825         1062 :               && i != OMP_LIST_REDUCTION_INSCAN
    8826         1062 :               && !is_loop)
    8827          670 :             clausesa[GFC_OMP_SPLIT_TEAMS].lists[i]
    8828          670 :               = code->ext.omp_clauses->lists[i];
    8829         6939 :           if (mask & GFC_OMP_MASK_PARALLEL
    8830         5592 :               && i != OMP_LIST_REDUCTION_INSCAN
    8831         3728 :               && !(mask & GFC_OMP_MASK_TASKLOOP)
    8832         3556 :               && !is_loop)
    8833         3486 :             clausesa[GFC_OMP_SPLIT_PARALLEL].lists[i]
    8834         3486 :               = code->ext.omp_clauses->lists[i];
    8835         3453 :           else if (mask & GFC_OMP_MASK_DO)
    8836         2249 :             clausesa[GFC_OMP_SPLIT_DO].lists[i]
    8837         2249 :               = code->ext.omp_clauses->lists[i];
    8838         6939 :           if (mask & GFC_OMP_MASK_SIMD)
    8839         2469 :             clausesa[GFC_OMP_SPLIT_SIMD].lists[i]
    8840         2469 :               = code->ext.omp_clauses->lists[i];
    8841              :         }
    8842         2313 :       if (mask & GFC_OMP_MASK_TARGET)
    8843          351 :         clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_IN_REDUCTION]
    8844          351 :           = code->ext.omp_clauses->lists[OMP_LIST_IN_REDUCTION];
    8845         2313 :       if (mask & GFC_OMP_MASK_TASKLOOP)
    8846          163 :         clausesa[GFC_OMP_SPLIT_TASKLOOP].lists[OMP_LIST_IN_REDUCTION]
    8847          163 :           = code->ext.omp_clauses->lists[OMP_LIST_IN_REDUCTION];
    8848              :       /* Linear clause is supported on do and simd,
    8849              :          put it on the innermost one.  */
    8850         2313 :       clausesa[innermost].lists[OMP_LIST_LINEAR]
    8851         2313 :         = code->ext.omp_clauses->lists[OMP_LIST_LINEAR];
    8852              :     }
    8853              :    /* Propagate firstprivate/lastprivate/reduction vars to
    8854              :       shared (parallel, teams) and map-tofrom (target).  */
    8855         2313 :    if (mask & GFC_OMP_MASK_TARGET)
    8856          351 :      gfc_add_clause_implicitly (&clausesa[GFC_OMP_SPLIT_TARGET],
    8857              :                                 code->ext.omp_clauses, true, false);
    8858         2313 :    if ((mask & GFC_OMP_MASK_PARALLEL) && innermost != GFC_OMP_MASK_PARALLEL)
    8859         1864 :      gfc_add_clause_implicitly (&clausesa[GFC_OMP_SPLIT_PARALLEL],
    8860              :                                 code->ext.omp_clauses, false,
    8861         1864 :                                 mask & GFC_OMP_MASK_DO);
    8862         2313 :    if (mask & GFC_OMP_MASK_TEAMS && innermost != GFC_OMP_MASK_TEAMS)
    8863          354 :      gfc_add_clause_implicitly (&clausesa[GFC_OMP_SPLIT_TEAMS],
    8864              :                                 code->ext.omp_clauses, false, false);
    8865         2313 :    if (((mask & (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO))
    8866              :         == (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO))
    8867         1744 :        && !is_loop)
    8868         1709 :     clausesa[GFC_OMP_SPLIT_DO].nowait = true;
    8869              : 
    8870              :    /* Distribute allocate clause to do, parallel, distribute, teams, target
    8871              :       and taskloop.  The code below iterates over variables in the
    8872              :       allocate list and checks if that available is also in any
    8873              :       privatization clause on those construct.  If yes, then we add it
    8874              :       to the list of 'allocate'ed variables for that construct.  If a
    8875              :       variable is found in none of them then we issue an error.  */
    8876              : 
    8877         2313 :    if (code->ext.omp_clauses->lists[OMP_LIST_ALLOCATE])
    8878              :      {
    8879              :        gfc_omp_namelist *alloc_nl, *priv_nl;
    8880              :        gfc_omp_namelist *tails[GFC_OMP_SPLIT_NUM];
    8881          104 :        for (alloc_nl = code->ext.omp_clauses->lists[OMP_LIST_ALLOCATE];
    8882          181 :            alloc_nl; alloc_nl = alloc_nl->next)
    8883              :          {
    8884              :            bool found = false;
    8885          728 :            for (int i = GFC_OMP_SPLIT_DO; i <= GFC_OMP_SPLIT_TASKLOOP; i++)
    8886              :              {
    8887              :                gfc_omp_namelist *p;
    8888              :                int list;
    8889        24960 :                for (list = 0; list < OMP_LIST_NUM; list++)
    8890              :                  {
    8891        24336 :                    switch (list)
    8892              :                    {
    8893         5616 :                      case OMP_LIST_PRIVATE:
    8894         5616 :                      case OMP_LIST_FIRSTPRIVATE:
    8895         5616 :                      case OMP_LIST_LASTPRIVATE:
    8896         5616 :                      case OMP_LIST_REDUCTION:
    8897         5616 :                      case OMP_LIST_REDUCTION_INSCAN:
    8898         5616 :                      case OMP_LIST_REDUCTION_TASK:
    8899         5616 :                      case OMP_LIST_IN_REDUCTION:
    8900         5616 :                      case OMP_LIST_TASK_REDUCTION:
    8901         5616 :                      case OMP_LIST_LINEAR:
    8902         6092 :                        for (priv_nl = clausesa[i].lists[list]; priv_nl;
    8903          476 :                             priv_nl = priv_nl->next)
    8904          476 :                          if (alloc_nl->sym == priv_nl->sym)
    8905              :                            {
    8906          131 :                              found = true;
    8907          131 :                              p = gfc_get_omp_namelist ();
    8908          131 :                              p->sym = alloc_nl->sym;
    8909          131 :                              p->expr = alloc_nl->expr;
    8910          131 :                              p->u.align = alloc_nl->u.align;
    8911          131 :                              p->u2.allocator = alloc_nl->u2.allocator;
    8912          131 :                              p->where = alloc_nl->where;
    8913          131 :                              if (clausesa[i].lists[OMP_LIST_ALLOCATE] == NULL)
    8914              :                                {
    8915          109 :                                  clausesa[i].lists[OMP_LIST_ALLOCATE] = p;
    8916          109 :                                  tails[i] = p;
    8917              :                                }
    8918              :                              else
    8919              :                                {
    8920           22 :                                  tails[i]->next = p;
    8921           22 :                                  tails[i] = tails[i]->next;
    8922              :                                }
    8923              :                            }
    8924              :                        break;
    8925              :                      default:
    8926              :                        break;
    8927              :                    }
    8928              :                  }
    8929              :              }
    8930          104 :            if (!found)
    8931            1 :              gfc_error ("%qs specified in %<allocate%> clause at %L but not "
    8932              :                         "in an explicit privatization clause",
    8933            1 :                         alloc_nl->sym->name, &alloc_nl->where);
    8934              :          }
    8935              :      }
    8936              : }
    8937              : 
    8938              : static tree
    8939          542 : gfc_trans_omp_do_simd (gfc_code *code, stmtblock_t *pblock,
    8940              :                        gfc_omp_clauses *clausesa, tree omp_clauses)
    8941              : {
    8942          542 :   stmtblock_t block;
    8943          542 :   gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
    8944          542 :   tree stmt, body, omp_do_clauses = NULL_TREE;
    8945          542 :   bool free_clausesa = false;
    8946              : 
    8947          542 :   if (pblock == NULL)
    8948          411 :     gfc_start_block (&block);
    8949              :   else
    8950          131 :     gfc_init_block (&block);
    8951              : 
    8952          542 :   if (clausesa == NULL)
    8953              :     {
    8954          126 :       clausesa = clausesa_buf;
    8955          126 :       gfc_split_omp_clauses (code, clausesa);
    8956          126 :       free_clausesa = true;
    8957              :     }
    8958          542 :   if (flag_openmp)
    8959          537 :     omp_do_clauses
    8960          537 :       = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_DO], code->loc);
    8961          673 :   body = gfc_trans_omp_do (code, EXEC_OMP_SIMD, pblock ? pblock : &block,
    8962              :                            &clausesa[GFC_OMP_SPLIT_SIMD], omp_clauses);
    8963          542 :   if (pblock == NULL)
    8964              :     {
    8965          411 :       if (TREE_CODE (body) != BIND_EXPR)
    8966          411 :         body = build3_v (BIND_EXPR, NULL, body, poplevel (1, 0));
    8967              :       else
    8968            0 :         poplevel (0, 0);
    8969              :     }
    8970          131 :   else if (TREE_CODE (body) != BIND_EXPR)
    8971          131 :     body = build3_v (BIND_EXPR, NULL, body, NULL_TREE);
    8972          542 :   if (flag_openmp)
    8973              :     {
    8974          537 :       stmt = make_node (OMP_FOR);
    8975          537 :       SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc));
    8976          537 :       TREE_TYPE (stmt) = void_type_node;
    8977          537 :       OMP_FOR_BODY (stmt) = body;
    8978          537 :       OMP_FOR_CLAUSES (stmt) = omp_do_clauses;
    8979              :     }
    8980              :   else
    8981              :     stmt = body;
    8982          542 :   gfc_add_expr_to_block (&block, stmt);
    8983          542 :   if (free_clausesa)
    8984          126 :     gfc_free_split_omp_clauses (code, clausesa);
    8985          542 :   return gfc_finish_block (&block);
    8986              : }
    8987              : 
    8988              : static tree
    8989         1328 : gfc_trans_omp_parallel_do (gfc_code *code, bool is_loop, stmtblock_t *pblock,
    8990              :                            gfc_omp_clauses *clausesa)
    8991              : {
    8992         1328 :   stmtblock_t block, *new_pblock = pblock;
    8993         1328 :   gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
    8994         1328 :   tree stmt, omp_clauses = NULL_TREE;
    8995         1328 :   bool free_clausesa = false;
    8996              : 
    8997         1328 :   if (pblock == NULL)
    8998         1116 :     gfc_start_block (&block);
    8999              :   else
    9000          212 :     gfc_init_block (&block);
    9001              : 
    9002         1328 :   if (clausesa == NULL)
    9003              :     {
    9004         1116 :       clausesa = clausesa_buf;
    9005         1116 :       gfc_split_omp_clauses (code, clausesa);
    9006         1116 :       free_clausesa = true;
    9007              :     }
    9008         1328 :   omp_clauses
    9009         1328 :     = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_PARALLEL],
    9010              :                              code->loc);
    9011         1328 :   if (pblock == NULL)
    9012              :     {
    9013         1116 :       if (!clausesa[GFC_OMP_SPLIT_DO].ordered
    9014         1107 :           && clausesa[GFC_OMP_SPLIT_DO].sched_kind != OMP_SCHED_STATIC)
    9015              :         new_pblock = &block;
    9016              :       else
    9017           65 :         pushlevel ();
    9018              :     }
    9019         2621 :   stmt = gfc_trans_omp_do (code, is_loop ? EXEC_OMP_LOOP : EXEC_OMP_DO,
    9020              :                            new_pblock, &clausesa[GFC_OMP_SPLIT_DO],
    9021              :                            omp_clauses);
    9022         1328 :   if (pblock == NULL)
    9023              :     {
    9024         1116 :       if (TREE_CODE (stmt) != BIND_EXPR)
    9025         1100 :         stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
    9026              :       else
    9027           16 :         poplevel (0, 0);
    9028              :     }
    9029          212 :   else if (TREE_CODE (stmt) != BIND_EXPR)
    9030          212 :     stmt = build3_v (BIND_EXPR, NULL, stmt, NULL_TREE);
    9031         1328 :   stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL,
    9032              :                      void_type_node, stmt, omp_clauses);
    9033         1328 :   OMP_PARALLEL_COMBINED (stmt) = 1;
    9034         1328 :   gfc_add_expr_to_block (&block, stmt);
    9035         1328 :   if (free_clausesa)
    9036         1116 :     gfc_free_split_omp_clauses (code, clausesa);
    9037         1328 :   return gfc_finish_block (&block);
    9038              : }
    9039              : 
    9040              : static tree
    9041          416 : gfc_trans_omp_parallel_do_simd (gfc_code *code, stmtblock_t *pblock,
    9042              :                                 gfc_omp_clauses *clausesa)
    9043              : {
    9044          416 :   stmtblock_t block;
    9045          416 :   gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
    9046          416 :   tree stmt, omp_clauses = NULL_TREE;
    9047          416 :   bool free_clausesa = false;
    9048              : 
    9049          416 :   if (pblock == NULL)
    9050          285 :     gfc_start_block (&block);
    9051              :   else
    9052          131 :     gfc_init_block (&block);
    9053              : 
    9054          416 :   if (clausesa == NULL)
    9055              :     {
    9056          285 :       clausesa = clausesa_buf;
    9057          285 :       gfc_split_omp_clauses (code, clausesa);
    9058          285 :       free_clausesa = true;
    9059              :     }
    9060          416 :   if (flag_openmp)
    9061          413 :     omp_clauses
    9062          413 :       = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_PARALLEL],
    9063              :                                code->loc);
    9064          416 :   if (pblock == NULL)
    9065          285 :     pushlevel ();
    9066          416 :   stmt = gfc_trans_omp_do_simd (code, pblock, clausesa, omp_clauses);
    9067          416 :   if (pblock == NULL)
    9068              :     {
    9069          285 :       if (TREE_CODE (stmt) != BIND_EXPR)
    9070          214 :         stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
    9071              :       else
    9072           71 :         poplevel (0, 0);
    9073              :     }
    9074          131 :   else if (TREE_CODE (stmt) != BIND_EXPR)
    9075          131 :     stmt = build3_v (BIND_EXPR, NULL, stmt, NULL_TREE);
    9076          416 :   if (flag_openmp)
    9077              :     {
    9078          413 :       stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL,
    9079              :                          void_type_node, stmt, omp_clauses);
    9080          413 :       OMP_PARALLEL_COMBINED (stmt) = 1;
    9081              :     }
    9082          416 :   gfc_add_expr_to_block (&block, stmt);
    9083          416 :   if (free_clausesa)
    9084          285 :     gfc_free_split_omp_clauses (code, clausesa);
    9085          416 :   return gfc_finish_block (&block);
    9086              : }
    9087              : 
    9088              : static tree
    9089           54 : gfc_trans_omp_parallel_sections (gfc_code *code)
    9090              : {
    9091           54 :   stmtblock_t block;
    9092           54 :   gfc_omp_clauses section_clauses;
    9093           54 :   tree stmt, omp_clauses;
    9094              : 
    9095           54 :   memset (&section_clauses, 0, sizeof (section_clauses));
    9096           54 :   section_clauses.nowait = true;
    9097              : 
    9098           54 :   gfc_start_block (&block);
    9099           54 :   omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
    9100              :                                        code->loc);
    9101           54 :   pushlevel ();
    9102           54 :   stmt = gfc_trans_omp_sections (code, &section_clauses);
    9103           54 :   if (TREE_CODE (stmt) != BIND_EXPR)
    9104           54 :     stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
    9105              :   else
    9106            0 :     poplevel (0, 0);
    9107           54 :   stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL,
    9108              :                      void_type_node, stmt, omp_clauses);
    9109           54 :   OMP_PARALLEL_COMBINED (stmt) = 1;
    9110           54 :   gfc_add_expr_to_block (&block, stmt);
    9111           54 :   return gfc_finish_block (&block);
    9112              : }
    9113              : 
    9114              : static tree
    9115           50 : gfc_trans_omp_parallel_workshare (gfc_code *code)
    9116              : {
    9117           50 :   stmtblock_t block;
    9118           50 :   gfc_omp_clauses workshare_clauses;
    9119           50 :   tree stmt, omp_clauses;
    9120              : 
    9121           50 :   memset (&workshare_clauses, 0, sizeof (workshare_clauses));
    9122           50 :   workshare_clauses.nowait = true;
    9123              : 
    9124           50 :   gfc_start_block (&block);
    9125           50 :   omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
    9126              :                                        code->loc);
    9127           50 :   pushlevel ();
    9128           50 :   stmt = gfc_trans_omp_workshare (code, &workshare_clauses);
    9129           50 :   stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
    9130           50 :   stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL,
    9131              :                      void_type_node, stmt, omp_clauses);
    9132           50 :   OMP_PARALLEL_COMBINED (stmt) = 1;
    9133           50 :   gfc_add_expr_to_block (&block, stmt);
    9134           50 :   return gfc_finish_block (&block);
    9135              : }
    9136              : 
    9137              : static tree
    9138           53 : gfc_trans_omp_scope (gfc_code *code)
    9139              : {
    9140           53 :   stmtblock_t block;
    9141           53 :   tree body = gfc_trans_code (code->block->next);
    9142           53 :   if (IS_EMPTY_STMT (body))
    9143              :     return body;
    9144           51 :   gfc_start_block (&block);
    9145           51 :   tree omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
    9146              :                                             code->loc);
    9147           51 :   tree stmt = make_node (OMP_SCOPE);
    9148           51 :   SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc));
    9149           51 :   TREE_TYPE (stmt) = void_type_node;
    9150           51 :   OMP_SCOPE_BODY (stmt) = body;
    9151           51 :   OMP_SCOPE_CLAUSES (stmt) = omp_clauses;
    9152           51 :   gfc_add_expr_to_block (&block, stmt);
    9153           51 :   return gfc_finish_block (&block);
    9154              : }
    9155              : 
    9156              : static tree
    9157          129 : gfc_trans_omp_sections (gfc_code *code, gfc_omp_clauses *clauses)
    9158              : {
    9159          129 :   stmtblock_t block, body;
    9160          129 :   tree omp_clauses, stmt;
    9161          129 :   bool has_lastprivate = clauses->lists[OMP_LIST_LASTPRIVATE] != NULL;
    9162          129 :   location_t loc = gfc_get_location (&code->loc);
    9163              : 
    9164          129 :   gfc_start_block (&block);
    9165              : 
    9166          129 :   omp_clauses = gfc_trans_omp_clauses (&block, clauses, code->loc);
    9167              : 
    9168          129 :   gfc_init_block (&body);
    9169          499 :   for (code = code->block; code; code = code->block)
    9170              :     {
    9171              :       /* Last section is special because of lastprivate, so even if it
    9172              :          is empty, chain it in.  */
    9173          370 :       stmt = gfc_trans_omp_code (code->next,
    9174          370 :                                  has_lastprivate && code->block == NULL);
    9175          370 :       if (! IS_EMPTY_STMT (stmt))
    9176              :         {
    9177          280 :           stmt = build1_v (OMP_SECTION, stmt);
    9178          280 :           gfc_add_expr_to_block (&body, stmt);
    9179              :         }
    9180              :     }
    9181          129 :   stmt = gfc_finish_block (&body);
    9182              : 
    9183          129 :   stmt = build2_loc (loc, OMP_SECTIONS, void_type_node, stmt, omp_clauses);
    9184          129 :   gfc_add_expr_to_block (&block, stmt);
    9185              : 
    9186          129 :   return gfc_finish_block (&block);
    9187              : }
    9188              : 
    9189              : static tree
    9190          556 : gfc_trans_omp_single (gfc_code *code, gfc_omp_clauses *clauses)
    9191              : {
    9192          556 :   stmtblock_t block;
    9193          556 :   gfc_start_block (&block);
    9194          556 :   tree omp_clauses = gfc_trans_omp_clauses (&block, clauses, code->loc);
    9195          556 :   tree stmt = gfc_trans_omp_code (code->block->next, true);
    9196          556 :   stmt = build2_loc (gfc_get_location (&code->loc), OMP_SINGLE, void_type_node,
    9197              :                      stmt, omp_clauses);
    9198          556 :   gfc_add_expr_to_block (&block, stmt);
    9199          556 :   return gfc_finish_block (&block);
    9200              : }
    9201              : 
    9202              : static tree
    9203         1123 : gfc_trans_omp_task (gfc_code *code)
    9204              : {
    9205         1123 :   stmtblock_t block;
    9206         1123 :   tree stmt, omp_clauses;
    9207              : 
    9208         1123 :   gfc_start_block (&block);
    9209         1123 :   omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
    9210              :                                        code->loc);
    9211         1123 :   pushlevel ();
    9212         1123 :   stmt = gfc_trans_omp_code (code->block->next, true);
    9213         1123 :   stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
    9214         1123 :   stmt = build2_loc (gfc_get_location (&code->loc), OMP_TASK, void_type_node,
    9215              :                      stmt, omp_clauses);
    9216         1123 :   gfc_add_expr_to_block (&block, stmt);
    9217         1123 :   return gfc_finish_block (&block);
    9218              : }
    9219              : 
    9220              : static tree
    9221          181 : gfc_trans_omp_taskgroup (gfc_code *code)
    9222              : {
    9223          181 :   stmtblock_t block;
    9224          181 :   gfc_start_block (&block);
    9225          181 :   tree body = gfc_trans_code (code->block->next);
    9226          181 :   tree stmt = make_node (OMP_TASKGROUP);
    9227          181 :   SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc));
    9228          181 :   TREE_TYPE (stmt) = void_type_node;
    9229          181 :   OMP_TASKGROUP_BODY (stmt) = body;
    9230          181 :   OMP_TASKGROUP_CLAUSES (stmt) = gfc_trans_omp_clauses (&block,
    9231              :                                                         code->ext.omp_clauses,
    9232              :                                                         code->loc);
    9233          181 :   gfc_add_expr_to_block (&block, stmt);
    9234          181 :   return gfc_finish_block (&block);
    9235              : }
    9236              : 
    9237              : static tree
    9238          146 : gfc_trans_omp_taskwait (gfc_code *code)
    9239              : {
    9240          146 :   if (!code->ext.omp_clauses)
    9241              :     {
    9242          132 :       tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT);
    9243          132 :       return build_call_expr_loc (input_location, decl, 0);
    9244              :     }
    9245           14 :   stmtblock_t block;
    9246           14 :   gfc_start_block (&block);
    9247           14 :   tree stmt = make_node (OMP_TASK);
    9248           14 :   SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc));
    9249           14 :   TREE_TYPE (stmt) = void_type_node;
    9250           14 :   OMP_TASK_BODY (stmt) = NULL_TREE;
    9251           14 :   OMP_TASK_CLAUSES (stmt) = gfc_trans_omp_clauses (&block,
    9252              :                                                    code->ext.omp_clauses,
    9253              :                                                    code->loc);
    9254           14 :   gfc_add_expr_to_block (&block, stmt);
    9255           14 :   return gfc_finish_block (&block);
    9256              : }
    9257              : 
    9258              : static tree
    9259            8 : gfc_trans_omp_taskyield (void)
    9260              : {
    9261            8 :   tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TASKYIELD);
    9262            8 :   return build_call_expr_loc (input_location, decl, 0);
    9263              : }
    9264              : 
    9265              : static tree
    9266          347 : gfc_trans_omp_distribute (gfc_code *code, gfc_omp_clauses *clausesa)
    9267              : {
    9268          347 :   stmtblock_t block;
    9269          347 :   gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
    9270          347 :   tree stmt, omp_clauses = NULL_TREE;
    9271          347 :   bool free_clausesa = false;
    9272              : 
    9273          347 :   gfc_start_block (&block);
    9274          347 :   if (clausesa == NULL)
    9275              :     {
    9276          113 :       clausesa = clausesa_buf;
    9277          113 :       gfc_split_omp_clauses (code, clausesa);
    9278          113 :       free_clausesa = true;
    9279              :     }
    9280          347 :   if (flag_openmp)
    9281          347 :     omp_clauses
    9282          347 :       = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_DISTRIBUTE],
    9283              :                                code->loc);
    9284          347 :   switch (code->op)
    9285              :     {
    9286            0 :     case EXEC_OMP_DISTRIBUTE:
    9287            0 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
    9288            0 :     case EXEC_OMP_TEAMS_DISTRIBUTE:
    9289              :       /* This is handled in gfc_trans_omp_do.  */
    9290            0 :       gcc_unreachable ();
    9291          132 :       break;
    9292          132 :     case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
    9293          132 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
    9294          132 :     case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
    9295          132 :       stmt = gfc_trans_omp_parallel_do (code, false, &block, clausesa);
    9296          132 :       if (TREE_CODE (stmt) != BIND_EXPR)
    9297          132 :         stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
    9298              :       else
    9299            0 :         poplevel (0, 0);
    9300              :       break;
    9301          115 :     case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
    9302          115 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
    9303          115 :     case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
    9304          115 :       stmt = gfc_trans_omp_parallel_do_simd (code, &block, clausesa);
    9305          115 :       if (TREE_CODE (stmt) != BIND_EXPR)
    9306          115 :         stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
    9307              :       else
    9308            0 :         poplevel (0, 0);
    9309              :       break;
    9310          100 :     case EXEC_OMP_DISTRIBUTE_SIMD:
    9311          100 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
    9312          100 :     case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
    9313          100 :       stmt = gfc_trans_omp_do (code, EXEC_OMP_SIMD, &block,
    9314              :                                &clausesa[GFC_OMP_SPLIT_SIMD], NULL_TREE);
    9315          100 :       if (TREE_CODE (stmt) != BIND_EXPR)
    9316          100 :         stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
    9317              :       else
    9318            0 :         poplevel (0, 0);
    9319              :       break;
    9320            0 :     default:
    9321            0 :       gcc_unreachable ();
    9322              :     }
    9323          347 :   if (flag_openmp)
    9324              :     {
    9325          347 :       tree distribute = make_node (OMP_DISTRIBUTE);
    9326          347 :       SET_EXPR_LOCATION (distribute, gfc_get_location (&code->loc));
    9327          347 :       TREE_TYPE (distribute) = void_type_node;
    9328          347 :       OMP_FOR_BODY (distribute) = stmt;
    9329          347 :       OMP_FOR_CLAUSES (distribute) = omp_clauses;
    9330          347 :       stmt = distribute;
    9331              :     }
    9332          347 :   gfc_add_expr_to_block (&block, stmt);
    9333          347 :   if (free_clausesa)
    9334          113 :     gfc_free_split_omp_clauses (code, clausesa);
    9335          347 :   return gfc_finish_block (&block);
    9336              : }
    9337              : 
    9338              : static tree
    9339          496 : gfc_trans_omp_teams (gfc_code *code, gfc_omp_clauses *clausesa,
    9340              :                      tree omp_clauses)
    9341              : {
    9342          496 :   stmtblock_t block;
    9343          496 :   gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
    9344          496 :   tree stmt;
    9345          496 :   bool combined = true, free_clausesa = false;
    9346              : 
    9347          496 :   gfc_start_block (&block);
    9348          496 :   if (clausesa == NULL)
    9349              :     {
    9350          290 :       clausesa = clausesa_buf;
    9351          290 :       gfc_split_omp_clauses (code, clausesa);
    9352          290 :       free_clausesa = true;
    9353              :     }
    9354          496 :   if (flag_openmp)
    9355              :     {
    9356          496 :       omp_clauses
    9357          496 :         = chainon (omp_clauses,
    9358              :                    gfc_trans_omp_clauses (&block,
    9359              :                                           &clausesa[GFC_OMP_SPLIT_TEAMS],
    9360              :                                           code->loc));
    9361          496 :       pushlevel ();
    9362              :     }
    9363          496 :   switch (code->op)
    9364              :     {
    9365          215 :     case EXEC_OMP_TARGET_TEAMS:
    9366          215 :     case EXEC_OMP_TEAMS:
    9367          215 :       stmt = gfc_trans_omp_code (code->block->next, true);
    9368          215 :       combined = false;
    9369          215 :       break;
    9370           28 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
    9371           28 :     case EXEC_OMP_TEAMS_DISTRIBUTE:
    9372           28 :       stmt = gfc_trans_omp_do (code, EXEC_OMP_DISTRIBUTE, NULL,
    9373              :                                &clausesa[GFC_OMP_SPLIT_DISTRIBUTE],
    9374              :                                NULL);
    9375           28 :       break;
    9376           19 :     case EXEC_OMP_TARGET_TEAMS_LOOP:
    9377           19 :     case EXEC_OMP_TEAMS_LOOP:
    9378           19 :       stmt = gfc_trans_omp_do (code, EXEC_OMP_LOOP, NULL,
    9379              :                                &clausesa[GFC_OMP_SPLIT_DO],
    9380              :                                NULL);
    9381           19 :       break;
    9382          234 :     default:
    9383          234 :       stmt = gfc_trans_omp_distribute (code, clausesa);
    9384          234 :       break;
    9385              :     }
    9386          496 :   if (flag_openmp)
    9387              :     {
    9388          496 :       stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
    9389          496 :       stmt = build2_loc (gfc_get_location (&code->loc), OMP_TEAMS,
    9390              :                          void_type_node, stmt, omp_clauses);
    9391          496 :       if (combined)
    9392          281 :         OMP_TEAMS_COMBINED (stmt) = 1;
    9393              :     }
    9394          496 :   gfc_add_expr_to_block (&block, stmt);
    9395          496 :   if (free_clausesa)
    9396          290 :     gfc_free_split_omp_clauses (code, clausesa);
    9397          496 :   return gfc_finish_block (&block);
    9398              : }
    9399              : 
    9400              : static tree
    9401         2369 : gfc_trans_omp_target (gfc_code *code)
    9402              : {
    9403         2369 :   stmtblock_t block;
    9404         2369 :   gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM];
    9405         2369 :   tree stmt, omp_clauses = NULL_TREE;
    9406              : 
    9407         2369 :   gfc_start_block (&block);
    9408         2369 :   gfc_split_omp_clauses (code, clausesa);
    9409         2369 :   if (flag_openmp)
    9410         2369 :     omp_clauses
    9411         2369 :       = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_TARGET],
    9412              :                                code->loc);
    9413         2369 :   switch (code->op)
    9414              :     {
    9415         2018 :     case EXEC_OMP_TARGET:
    9416         2018 :       pushlevel ();
    9417         2018 :       stmt = gfc_trans_omp_code (code->block->next, true);
    9418         2018 :       stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
    9419         2018 :       break;
    9420           23 :     case EXEC_OMP_TARGET_PARALLEL:
    9421           23 :       {
    9422           23 :         stmtblock_t iblock;
    9423              : 
    9424           23 :         pushlevel ();
    9425           23 :         gfc_start_block (&iblock);
    9426           23 :         tree inner_clauses
    9427           23 :           = gfc_trans_omp_clauses (&iblock, &clausesa[GFC_OMP_SPLIT_PARALLEL],
    9428              :                                    code->loc);
    9429           23 :         stmt = gfc_trans_omp_code (code->block->next, true);
    9430           23 :         stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
    9431              :                            inner_clauses);
    9432           23 :         gfc_add_expr_to_block (&iblock, stmt);
    9433           23 :         stmt = gfc_finish_block (&iblock);
    9434           23 :         if (TREE_CODE (stmt) != BIND_EXPR)
    9435           20 :           stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
    9436              :         else
    9437            3 :           poplevel (0, 0);
    9438              :       }
    9439           23 :       break;
    9440           80 :     case EXEC_OMP_TARGET_PARALLEL_DO:
    9441           80 :     case EXEC_OMP_TARGET_PARALLEL_LOOP:
    9442           80 :       stmt = gfc_trans_omp_parallel_do (code,
    9443              :                                         (code->op
    9444              :                                          == EXEC_OMP_TARGET_PARALLEL_LOOP),
    9445              :                                         &block, clausesa);
    9446           80 :       if (TREE_CODE (stmt) != BIND_EXPR)
    9447           80 :         stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
    9448              :       else
    9449            0 :         poplevel (0, 0);
    9450              :       break;
    9451           16 :     case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
    9452           16 :       stmt = gfc_trans_omp_parallel_do_simd (code, &block, clausesa);
    9453           16 :       if (TREE_CODE (stmt) != BIND_EXPR)
    9454           16 :         stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
    9455              :       else
    9456            0 :         poplevel (0, 0);
    9457              :       break;
    9458           26 :     case EXEC_OMP_TARGET_SIMD:
    9459           26 :       stmt = gfc_trans_omp_do (code, EXEC_OMP_SIMD, &block,
    9460              :                                &clausesa[GFC_OMP_SPLIT_SIMD], NULL_TREE);
    9461           26 :       if (TREE_CODE (stmt) != BIND_EXPR)
    9462           26 :         stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
    9463              :       else
    9464            0 :         poplevel (0, 0);
    9465              :       break;
    9466          206 :     default:
    9467          206 :       if (flag_openmp
    9468          206 :           && (clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_list
    9469          149 :               || clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit_list))
    9470              :         {
    9471           58 :           gfc_omp_clauses clausesb;
    9472           58 :           tree teams_clauses;
    9473              :           /* For combined !$omp target teams, the num_teams and
    9474              :              thread_limit clauses are evaluated before entering the
    9475              :              target construct.  */
    9476           58 :           memset (&clausesb, '\0', sizeof (clausesb));
    9477           58 :           clausesb.num_teams_list
    9478           58 :             = clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_list;
    9479           58 :           clausesb.num_teams_dims
    9480           58 :             = clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_dims;
    9481           58 :           clausesb.thread_limit_list
    9482           58 :             = clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit_list;
    9483           58 :           clausesb.thread_limit_strict
    9484           58 :             = clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit_strict;
    9485           58 :           clausesb.thread_limit_dims
    9486           58 :             = clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit_dims;
    9487           58 :           clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_list = NULL;
    9488           58 :           clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit_list = NULL;
    9489           58 :           teams_clauses
    9490           58 :             = gfc_trans_omp_clauses (&block, &clausesb, code->loc);
    9491           58 :           pushlevel ();
    9492           58 :           stmt = gfc_trans_omp_teams (code, clausesa, teams_clauses);
    9493           58 :         }
    9494              :       else
    9495              :         {
    9496          148 :           pushlevel ();
    9497          148 :           stmt = gfc_trans_omp_teams (code, clausesa, NULL_TREE);
    9498              :         }
    9499          206 :       if (TREE_CODE (stmt) != BIND_EXPR)
    9500          206 :         stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
    9501              :       else
    9502            0 :         poplevel (0, 0);
    9503              :       break;
    9504              :     }
    9505         2369 :   if (flag_openmp)
    9506              :     {
    9507         2369 :       stmt = build2_loc (gfc_get_location (&code->loc), OMP_TARGET,
    9508              :                          void_type_node, stmt, omp_clauses);
    9509         2369 :       if (code->op != EXEC_OMP_TARGET)
    9510          351 :         OMP_TARGET_COMBINED (stmt) = 1;
    9511         2369 :       cfun->has_omp_target = true;
    9512              :     }
    9513         2369 :   gfc_add_expr_to_block (&block, stmt);
    9514         2369 :   gfc_free_split_omp_clauses (code, clausesa);
    9515         2369 :   return gfc_finish_block (&block);
    9516              : }
    9517              : 
    9518              : static tree
    9519           79 : gfc_trans_omp_taskloop (gfc_code *code, gfc_exec_op op)
    9520              : {
    9521           79 :   stmtblock_t block;
    9522           79 :   gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM];
    9523           79 :   tree stmt, omp_clauses = NULL_TREE;
    9524              : 
    9525           79 :   gfc_start_block (&block);
    9526           79 :   gfc_split_omp_clauses (code, clausesa);
    9527           79 :   if (flag_openmp)
    9528           79 :     omp_clauses
    9529           79 :       = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_TASKLOOP],
    9530              :                                code->loc);
    9531           79 :   switch (op)
    9532              :     {
    9533            0 :     case EXEC_OMP_TASKLOOP:
    9534              :       /* This is handled in gfc_trans_omp_do.  */
    9535            0 :       gcc_unreachable ();
    9536           79 :       break;
    9537           79 :     case EXEC_OMP_TASKLOOP_SIMD:
    9538           79 :       stmt = gfc_trans_omp_do (code, EXEC_OMP_SIMD, &block,
    9539              :                                &clausesa[GFC_OMP_SPLIT_SIMD], NULL_TREE);
    9540           79 :       if (TREE_CODE (stmt) != BIND_EXPR)
    9541           79 :         stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
    9542              :       else
    9543            0 :         poplevel (0, 0);
    9544           79 :       break;
    9545            0 :     default:
    9546            0 :       gcc_unreachable ();
    9547              :     }
    9548           79 :   if (flag_openmp)
    9549              :     {
    9550           79 :       tree taskloop = make_node (OMP_TASKLOOP);
    9551           79 :       SET_EXPR_LOCATION (taskloop, gfc_get_location (&code->loc));
    9552           79 :       TREE_TYPE (taskloop) = void_type_node;
    9553           79 :       OMP_FOR_BODY (taskloop) = stmt;
    9554           79 :       OMP_FOR_CLAUSES (taskloop) = omp_clauses;
    9555           79 :       stmt = taskloop;
    9556              :     }
    9557           79 :   gfc_add_expr_to_block (&block, stmt);
    9558           79 :   gfc_free_split_omp_clauses (code, clausesa);
    9559           79 :   return gfc_finish_block (&block);
    9560              : }
    9561              : 
    9562              : static tree
    9563           84 : gfc_trans_omp_master_masked_taskloop (gfc_code *code, gfc_exec_op op)
    9564              : {
    9565           84 :   gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM];
    9566           84 :   stmtblock_t block;
    9567           84 :   tree stmt;
    9568              : 
    9569           84 :   if (op != EXEC_OMP_MASTER_TASKLOOP_SIMD
    9570           56 :       && code->op != EXEC_OMP_MASTER_TASKLOOP)
    9571           45 :     gfc_split_omp_clauses (code, clausesa);
    9572              : 
    9573           84 :   pushlevel ();
    9574           84 :   if (op == EXEC_OMP_MASKED_TASKLOOP_SIMD
    9575           84 :       || op == EXEC_OMP_MASTER_TASKLOOP_SIMD)
    9576           48 :     stmt = gfc_trans_omp_taskloop (code, EXEC_OMP_TASKLOOP_SIMD);
    9577              :   else
    9578              :     {
    9579           36 :       gcc_assert (op == EXEC_OMP_MASKED_TASKLOOP
    9580              :                   || op == EXEC_OMP_MASTER_TASKLOOP);
    9581           36 :       stmt = gfc_trans_omp_do (code, EXEC_OMP_TASKLOOP, NULL,
    9582           36 :                                code->op != EXEC_OMP_MASTER_TASKLOOP
    9583              :                                ? &clausesa[GFC_OMP_SPLIT_TASKLOOP]
    9584              :                                : code->ext.omp_clauses, NULL);
    9585              :     }
    9586           84 :   if (TREE_CODE (stmt) != BIND_EXPR)
    9587           55 :     stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
    9588              :   else
    9589           29 :     poplevel (0, 0);
    9590           84 :   gfc_start_block (&block);
    9591           84 :   if (op == EXEC_OMP_MASKED_TASKLOOP || op == EXEC_OMP_MASKED_TASKLOOP_SIMD)
    9592              :     {
    9593           35 :       tree clauses = gfc_trans_omp_clauses (&block,
    9594              :                                             &clausesa[GFC_OMP_SPLIT_MASKED],
    9595              :                                             code->loc);
    9596           35 :       tree msk = make_node (OMP_MASKED);
    9597           35 :       SET_EXPR_LOCATION (msk, gfc_get_location (&code->loc));
    9598           35 :       TREE_TYPE (msk) = void_type_node;
    9599           35 :       OMP_MASKED_BODY (msk) = stmt;
    9600           35 :       OMP_MASKED_CLAUSES (msk) = clauses;
    9601           35 :       OMP_MASKED_COMBINED (msk) = 1;
    9602           35 :       gfc_add_expr_to_block (&block, msk);
    9603              :     }
    9604              :   else
    9605              :     {
    9606           49 :       gcc_assert (op == EXEC_OMP_MASTER_TASKLOOP
    9607              :                   || op == EXEC_OMP_MASTER_TASKLOOP_SIMD);
    9608           49 :       stmt = build1_v (OMP_MASTER, stmt);
    9609           49 :       gfc_add_expr_to_block (&block, stmt);
    9610              :     }
    9611           84 :   if (op != EXEC_OMP_MASTER_TASKLOOP_SIMD
    9612           56 :       && code->op != EXEC_OMP_MASTER_TASKLOOP)
    9613           45 :     gfc_free_split_omp_clauses (code, clausesa);
    9614           84 :   return gfc_finish_block (&block);
    9615              : }
    9616              : 
    9617              : static tree
    9618           61 : gfc_trans_omp_parallel_master_masked (gfc_code *code)
    9619              : {
    9620           61 :   stmtblock_t block;
    9621           61 :   tree stmt, omp_clauses;
    9622           61 :   gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM];
    9623           61 :   bool parallel_combined = false;
    9624              : 
    9625           61 :   if (code->op != EXEC_OMP_PARALLEL_MASTER)
    9626           50 :     gfc_split_omp_clauses (code, clausesa);
    9627              : 
    9628           61 :   gfc_start_block (&block);
    9629           61 :   omp_clauses = gfc_trans_omp_clauses (&block,
    9630           61 :                                        code->op == EXEC_OMP_PARALLEL_MASTER
    9631              :                                        ? code->ext.omp_clauses
    9632              :                                        : &clausesa[GFC_OMP_SPLIT_PARALLEL],
    9633              :                                        code->loc);
    9634           61 :   pushlevel ();
    9635           61 :   if (code->op == EXEC_OMP_PARALLEL_MASTER)
    9636           11 :     stmt = gfc_trans_omp_master (code);
    9637           50 :   else if (code->op == EXEC_OMP_PARALLEL_MASKED)
    9638           11 :     stmt = gfc_trans_omp_masked (code, &clausesa[GFC_OMP_SPLIT_MASKED]);
    9639              :   else
    9640              :     {
    9641           39 :       gfc_exec_op op;
    9642           39 :       switch (code->op)
    9643              :         {
    9644              :         case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
    9645              :           op = EXEC_OMP_MASKED_TASKLOOP;
    9646              :           break;
    9647            8 :         case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
    9648            8 :           op = EXEC_OMP_MASKED_TASKLOOP_SIMD;
    9649            8 :           break;
    9650           10 :         case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
    9651           10 :           op = EXEC_OMP_MASTER_TASKLOOP;
    9652           10 :           break;
    9653           14 :         case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
    9654           14 :           op = EXEC_OMP_MASTER_TASKLOOP_SIMD;
    9655           14 :           break;
    9656            0 :         default:
    9657            0 :           gcc_unreachable ();
    9658              :         }
    9659           39 :       stmt = gfc_trans_omp_master_masked_taskloop (code, op);
    9660           39 :       parallel_combined = true;
    9661              :     }
    9662           61 :   if (TREE_CODE (stmt) != BIND_EXPR)
    9663           48 :     stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
    9664              :   else
    9665           13 :     poplevel (0, 0);
    9666           61 :   stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL,
    9667              :                      void_type_node, stmt, omp_clauses);
    9668              :   /* masked does have just filter clause, but during gimplification
    9669              :      isn't represented by a gimplification omp context, so for
    9670              :        !$omp parallel masked don't set OMP_PARALLEL_COMBINED,
    9671              :      so that
    9672              :        !$omp parallel masked
    9673              :        !$omp taskloop simd lastprivate (x)
    9674              :      isn't confused with
    9675              :        !$omp parallel masked taskloop simd lastprivate (x)  */
    9676           61 :   if (parallel_combined)
    9677           39 :     OMP_PARALLEL_COMBINED (stmt) = 1;
    9678           61 :   gfc_add_expr_to_block (&block, stmt);
    9679           61 :   if (code->op != EXEC_OMP_PARALLEL_MASTER)
    9680           50 :     gfc_free_split_omp_clauses (code, clausesa);
    9681           61 :   return gfc_finish_block (&block);
    9682              : }
    9683              : 
    9684              : static tree
    9685         1389 : gfc_trans_omp_target_data (gfc_code *code)
    9686              : {
    9687         1389 :   stmtblock_t block;
    9688         1389 :   tree stmt, omp_clauses;
    9689              : 
    9690         1389 :   gfc_start_block (&block);
    9691         1389 :   omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
    9692              :                                        code->loc);
    9693         1389 :   stmt = gfc_trans_omp_code (code->block->next, true);
    9694         1389 :   stmt = build2_loc (gfc_get_location (&code->loc), OMP_TARGET_DATA,
    9695              :                      void_type_node, stmt, omp_clauses);
    9696         1389 :   gfc_add_expr_to_block (&block, stmt);
    9697         1389 :   return gfc_finish_block (&block);
    9698              : }
    9699              : 
    9700              : static tree
    9701          437 : gfc_trans_omp_target_enter_data (gfc_code *code)
    9702              : {
    9703          437 :   stmtblock_t block;
    9704          437 :   tree stmt, omp_clauses;
    9705              : 
    9706          437 :   gfc_start_block (&block);
    9707          437 :   omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
    9708              :                                        code->loc);
    9709          437 :   stmt = build1_loc (input_location, OMP_TARGET_ENTER_DATA, void_type_node,
    9710              :                      omp_clauses);
    9711          437 :   gfc_add_expr_to_block (&block, stmt);
    9712          437 :   return gfc_finish_block (&block);
    9713              : }
    9714              : 
    9715              : static tree
    9716          361 : gfc_trans_omp_target_exit_data (gfc_code *code)
    9717              : {
    9718          361 :   stmtblock_t block;
    9719          361 :   tree stmt, omp_clauses;
    9720              : 
    9721          361 :   gfc_start_block (&block);
    9722          361 :   omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
    9723              :                                        code->loc, false, false, code->op);
    9724          361 :   stmt = build1_loc (input_location, OMP_TARGET_EXIT_DATA, void_type_node,
    9725              :                      omp_clauses);
    9726          361 :   gfc_add_expr_to_block (&block, stmt);
    9727          361 :   return gfc_finish_block (&block);
    9728              : }
    9729              : 
    9730              : static tree
    9731         1708 : gfc_trans_omp_target_update (gfc_code *code)
    9732              : {
    9733         1708 :   stmtblock_t block;
    9734         1708 :   tree stmt, omp_clauses;
    9735              : 
    9736         1708 :   gfc_start_block (&block);
    9737         1708 :   omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
    9738              :                                        code->loc);
    9739         1708 :   stmt = build1_loc (input_location, OMP_TARGET_UPDATE, void_type_node,
    9740              :                      omp_clauses);
    9741         1708 :   gfc_add_expr_to_block (&block, stmt);
    9742         1708 :   return gfc_finish_block (&block);
    9743              : }
    9744              : 
    9745              : static tree
    9746            8 : gfc_trans_openmp_interop (gfc_code *code, gfc_omp_clauses *clauses)
    9747              : {
    9748            8 :   stmtblock_t block;
    9749            8 :   gfc_start_block (&block);
    9750            8 :   tree omp_clauses = gfc_trans_omp_clauses (&block, clauses, code->loc);
    9751            8 :   tree stmt = build1_loc (input_location, OMP_INTEROP, void_type_node,
    9752              :                           omp_clauses);
    9753            8 :   gfc_add_expr_to_block (&block, stmt);
    9754            8 :   return gfc_finish_block (&block);
    9755              : }
    9756              : 
    9757              : static tree
    9758           85 : gfc_trans_omp_workshare (gfc_code *code, gfc_omp_clauses *clauses)
    9759              : {
    9760           85 :   tree res, tmp, stmt;
    9761           85 :   stmtblock_t block, *pblock = NULL;
    9762           85 :   stmtblock_t singleblock;
    9763           85 :   int saved_ompws_flags;
    9764           85 :   bool singleblock_in_progress = false;
    9765              :   /* True if previous gfc_code in workshare construct is not workshared.  */
    9766           85 :   bool prev_singleunit;
    9767           85 :   location_t loc = gfc_get_location (&code->loc);
    9768              : 
    9769           85 :   code = code->block->next;
    9770              : 
    9771           85 :   pushlevel ();
    9772              : 
    9773           85 :   gfc_start_block (&block);
    9774           85 :   pblock = &block;
    9775              : 
    9776           85 :   ompws_flags = OMPWS_WORKSHARE_FLAG;
    9777           85 :   prev_singleunit = false;
    9778              : 
    9779              :   /* Translate statements one by one to trees until we reach
    9780              :      the end of the workshare construct.  Adjacent gfc_codes that
    9781              :      are a single unit of work are clustered and encapsulated in a
    9782              :      single OMP_SINGLE construct.  */
    9783          282 :   for (; code; code = code->next)
    9784              :     {
    9785          197 :       if (code->here != 0)
    9786              :         {
    9787            0 :           res = gfc_trans_label_here (code);
    9788            0 :           gfc_add_expr_to_block (pblock, res);
    9789              :         }
    9790              : 
    9791              :       /* No dependence analysis, use for clauses with wait.
    9792              :          If this is the last gfc_code, use default omp_clauses.  */
    9793          197 :       if (code->next == NULL && clauses->nowait)
    9794           60 :         ompws_flags |= OMPWS_NOWAIT;
    9795              : 
    9796              :       /* By default, every gfc_code is a single unit of work.  */
    9797          197 :       ompws_flags |= OMPWS_CURR_SINGLEUNIT;
    9798          197 :       ompws_flags &= ~(OMPWS_SCALARIZER_WS | OMPWS_SCALARIZER_BODY);
    9799              : 
    9800          197 :       switch (code->op)
    9801              :         {
    9802              :         case EXEC_NOP:
    9803              :           res = NULL_TREE;
    9804              :           break;
    9805              : 
    9806          125 :         case EXEC_ASSIGN:
    9807          125 :           res = gfc_trans_assign (code);
    9808          125 :           break;
    9809              : 
    9810            0 :         case EXEC_POINTER_ASSIGN:
    9811            0 :           res = gfc_trans_pointer_assign (code);
    9812            0 :           break;
    9813              : 
    9814            0 :         case EXEC_INIT_ASSIGN:
    9815            0 :           res = gfc_trans_init_assign (code);
    9816            0 :           break;
    9817              : 
    9818           24 :         case EXEC_FORALL:
    9819           24 :           res = gfc_trans_forall (code);
    9820           24 :           break;
    9821              : 
    9822           19 :         case EXEC_WHERE:
    9823           19 :           res = gfc_trans_where (code);
    9824           19 :           break;
    9825              : 
    9826            7 :         case EXEC_OMP_ATOMIC:
    9827            7 :           res = gfc_trans_omp_directive (code);
    9828            7 :           break;
    9829              : 
    9830           17 :         case EXEC_OMP_PARALLEL:
    9831           17 :         case EXEC_OMP_PARALLEL_DO:
    9832           17 :         case EXEC_OMP_PARALLEL_MASTER:
    9833           17 :         case EXEC_OMP_PARALLEL_SECTIONS:
    9834           17 :         case EXEC_OMP_PARALLEL_WORKSHARE:
    9835           17 :         case EXEC_OMP_CRITICAL:
    9836           17 :           saved_ompws_flags = ompws_flags;
    9837           17 :           ompws_flags = 0;
    9838           17 :           res = gfc_trans_omp_directive (code);
    9839           17 :           ompws_flags = saved_ompws_flags;
    9840           17 :           break;
    9841              : 
    9842            5 :         case EXEC_BLOCK:
    9843            5 :           res = gfc_trans_block_construct (code);
    9844            5 :           break;
    9845              : 
    9846            0 :         default:
    9847            0 :           gfc_internal_error ("gfc_trans_omp_workshare(): Bad statement code");
    9848              :         }
    9849              : 
    9850          197 :       input_location = gfc_get_location (&code->loc);
    9851              : 
    9852          197 :       if (res != NULL_TREE && ! IS_EMPTY_STMT (res))
    9853              :         {
    9854          197 :           if (prev_singleunit)
    9855              :             {
    9856           72 :               if (ompws_flags & OMPWS_CURR_SINGLEUNIT)
    9857              :                 /* Add current gfc_code to single block.  */
    9858           44 :                 gfc_add_expr_to_block (&singleblock, res);
    9859              :               else
    9860              :                 {
    9861              :                   /* Finish single block and add it to pblock.  */
    9862           28 :                   tmp = gfc_finish_block (&singleblock);
    9863           28 :                   tmp = build2_loc (loc, OMP_SINGLE,
    9864              :                                     void_type_node, tmp, NULL_TREE);
    9865           28 :                   gfc_add_expr_to_block (pblock, tmp);
    9866              :                   /* Add current gfc_code to pblock.  */
    9867           28 :                   gfc_add_expr_to_block (pblock, res);
    9868           28 :                   singleblock_in_progress = false;
    9869              :                 }
    9870              :             }
    9871              :           else
    9872              :             {
    9873          125 :               if (ompws_flags & OMPWS_CURR_SINGLEUNIT)
    9874              :                 {
    9875              :                   /* Start single block.  */
    9876           73 :                   gfc_init_block (&singleblock);
    9877           73 :                   gfc_add_expr_to_block (&singleblock, res);
    9878           73 :                   singleblock_in_progress = true;
    9879           73 :                   loc = gfc_get_location (&code->loc);
    9880              :                 }
    9881              :               else
    9882              :                 /* Add the new statement to the block.  */
    9883           52 :                 gfc_add_expr_to_block (pblock, res);
    9884              :             }
    9885          197 :           prev_singleunit = (ompws_flags & OMPWS_CURR_SINGLEUNIT) != 0;
    9886              :         }
    9887              :     }
    9888              : 
    9889              :   /* Finish remaining SINGLE block, if we were in the middle of one.  */
    9890           85 :   if (singleblock_in_progress)
    9891              :     {
    9892              :       /* Finish single block and add it to pblock.  */
    9893           45 :       tmp = gfc_finish_block (&singleblock);
    9894           45 :       tmp = build2_loc (loc, OMP_SINGLE, void_type_node, tmp,
    9895           45 :                         clauses->nowait
    9896           27 :                         ? build_omp_clause (input_location, OMP_CLAUSE_NOWAIT)
    9897              :                         : NULL_TREE);
    9898           45 :       gfc_add_expr_to_block (pblock, tmp);
    9899              :     }
    9900              : 
    9901           85 :   stmt = gfc_finish_block (pblock);
    9902           85 :   if (TREE_CODE (stmt) != BIND_EXPR)
    9903              :     {
    9904           65 :       if (!IS_EMPTY_STMT (stmt))
    9905              :         {
    9906           65 :           tree bindblock = poplevel (1, 0);
    9907           65 :           stmt = build3_v (BIND_EXPR, NULL, stmt, bindblock);
    9908              :         }
    9909              :       else
    9910            0 :         poplevel (0, 0);
    9911              :     }
    9912              :   else
    9913           20 :     poplevel (0, 0);
    9914              : 
    9915           85 :   if (IS_EMPTY_STMT (stmt) && !clauses->nowait)
    9916            0 :     stmt = gfc_trans_omp_barrier ();
    9917              : 
    9918           85 :   ompws_flags = 0;
    9919           85 :   return stmt;
    9920              : }
    9921              : 
    9922              : tree
    9923           76 : gfc_trans_oacc_declare (gfc_code *code)
    9924              : {
    9925           76 :   stmtblock_t block;
    9926           76 :   tree stmt, oacc_clauses;
    9927           76 :   enum tree_code construct_code;
    9928              : 
    9929           76 :   construct_code = OACC_DATA;
    9930              : 
    9931           76 :   gfc_start_block (&block);
    9932              : 
    9933           76 :   oacc_clauses = gfc_trans_omp_clauses (&block, code->ext.oacc_declare->clauses,
    9934              :                                         code->loc, false, true);
    9935           76 :   stmt = gfc_trans_omp_code (code->block->next, true);
    9936           76 :   stmt = build2_loc (input_location, construct_code, void_type_node, stmt,
    9937              :                      oacc_clauses);
    9938           76 :   gfc_add_expr_to_block (&block, stmt);
    9939              : 
    9940           76 :   return gfc_finish_block (&block);
    9941              : }
    9942              : 
    9943              : tree
    9944        12412 : gfc_trans_oacc_directive (gfc_code *code)
    9945              : {
    9946        12412 :   switch (code->op)
    9947              :     {
    9948         1556 :     case EXEC_OACC_PARALLEL_LOOP:
    9949         1556 :     case EXEC_OACC_KERNELS_LOOP:
    9950         1556 :     case EXEC_OACC_SERIAL_LOOP:
    9951         1556 :       return gfc_trans_oacc_combined_directive (code);
    9952         4189 :     case EXEC_OACC_PARALLEL:
    9953         4189 :     case EXEC_OACC_KERNELS:
    9954         4189 :     case EXEC_OACC_SERIAL:
    9955         4189 :     case EXEC_OACC_DATA:
    9956         4189 :     case EXEC_OACC_HOST_DATA:
    9957         4189 :       return gfc_trans_oacc_construct (code);
    9958         3377 :     case EXEC_OACC_LOOP:
    9959         3377 :       return gfc_trans_omp_do (code, code->op, NULL, code->ext.omp_clauses,
    9960         3377 :                                NULL);
    9961         2498 :     case EXEC_OACC_UPDATE:
    9962         2498 :     case EXEC_OACC_CACHE:
    9963         2498 :     case EXEC_OACC_ENTER_DATA:
    9964         2498 :     case EXEC_OACC_EXIT_DATA:
    9965         2498 :     case EXEC_OACC_INIT:
    9966         2498 :     case EXEC_OACC_SHUTDOWN:
    9967         2498 :     case EXEC_OACC_SET:
    9968         2498 :       return gfc_trans_oacc_executable_directive (code);
    9969          173 :     case EXEC_OACC_WAIT:
    9970          173 :       return gfc_trans_oacc_wait_directive (code);
    9971          543 :     case EXEC_OACC_ATOMIC:
    9972          543 :       return gfc_trans_omp_atomic (code);
    9973           76 :     case EXEC_OACC_DECLARE:
    9974           76 :       return gfc_trans_oacc_declare (code);
    9975            0 :     default:
    9976            0 :       gcc_unreachable ();
    9977              :     }
    9978              : }
    9979              : 
    9980              : tree
    9981        19403 : gfc_trans_omp_directive (gfc_code *code)
    9982              : {
    9983        19403 :   switch (code->op)
    9984              :     {
    9985           35 :     case EXEC_OMP_ALLOCATE:
    9986           35 :     case EXEC_OMP_ALLOCATORS:
    9987           35 :       return gfc_trans_omp_allocators (code);
    9988           10 :     case EXEC_OMP_ASSUME:
    9989           10 :       return gfc_trans_omp_assume (code);
    9990         2053 :     case EXEC_OMP_ATOMIC:
    9991         2053 :       return gfc_trans_omp_atomic (code);
    9992          604 :     case EXEC_OMP_BARRIER:
    9993          604 :       return gfc_trans_omp_barrier ();
    9994          310 :     case EXEC_OMP_CANCEL:
    9995          310 :       return gfc_trans_omp_cancel (code);
    9996          170 :     case EXEC_OMP_CANCELLATION_POINT:
    9997          170 :       return gfc_trans_omp_cancellation_point (code);
    9998          143 :     case EXEC_OMP_CRITICAL:
    9999          143 :       return gfc_trans_omp_critical (code);
   10000          108 :     case EXEC_OMP_DEPOBJ:
   10001          108 :       return gfc_trans_omp_depobj (code);
   10002         2457 :     case EXEC_OMP_DISTRIBUTE:
   10003         2457 :     case EXEC_OMP_DO:
   10004         2457 :     case EXEC_OMP_LOOP:
   10005         2457 :     case EXEC_OMP_SIMD:
   10006         2457 :     case EXEC_OMP_TASKLOOP:
   10007         2457 :     case EXEC_OMP_TILE:
   10008         2457 :     case EXEC_OMP_UNROLL:
   10009         2457 :       return gfc_trans_omp_do (code, code->op, NULL, code->ext.omp_clauses,
   10010         2457 :                                NULL);
   10011          128 :     case EXEC_OMP_DISPATCH:
   10012          128 :       return gfc_trans_omp_dispatch (code);
   10013          113 :     case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
   10014          113 :     case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
   10015          113 :     case EXEC_OMP_DISTRIBUTE_SIMD:
   10016          113 :       return gfc_trans_omp_distribute (code, NULL);
   10017          126 :     case EXEC_OMP_DO_SIMD:
   10018          126 :       return gfc_trans_omp_do_simd (code, NULL, NULL, NULL_TREE);
   10019           29 :     case EXEC_OMP_ERROR:
   10020           29 :       return gfc_trans_omp_error (code);
   10021           70 :     case EXEC_OMP_FLUSH:
   10022           70 :       return gfc_trans_omp_flush (code);
   10023           44 :     case EXEC_OMP_MASKED:
   10024           44 :       return gfc_trans_omp_masked (code, NULL);
   10025          105 :     case EXEC_OMP_MASTER:
   10026          105 :       return gfc_trans_omp_master (code);
   10027           45 :     case EXEC_OMP_MASKED_TASKLOOP:
   10028           45 :     case EXEC_OMP_MASKED_TASKLOOP_SIMD:
   10029           45 :     case EXEC_OMP_MASTER_TASKLOOP:
   10030           45 :     case EXEC_OMP_MASTER_TASKLOOP_SIMD:
   10031           45 :       return gfc_trans_omp_master_masked_taskloop (code, code->op);
   10032           88 :     case EXEC_OMP_METADIRECTIVE:
   10033           88 :       return gfc_trans_omp_metadirective (code);
   10034          521 :     case EXEC_OMP_ORDERED:
   10035          521 :       return gfc_trans_omp_ordered (code);
   10036         1908 :     case EXEC_OMP_PARALLEL:
   10037         1908 :       return gfc_trans_omp_parallel (code);
   10038         1092 :     case EXEC_OMP_PARALLEL_DO:
   10039         1092 :       return gfc_trans_omp_parallel_do (code, false, NULL, NULL);
   10040           24 :     case EXEC_OMP_PARALLEL_LOOP:
   10041           24 :       return gfc_trans_omp_parallel_do (code, true, NULL, NULL);
   10042          285 :     case EXEC_OMP_PARALLEL_DO_SIMD:
   10043          285 :       return gfc_trans_omp_parallel_do_simd (code, NULL, NULL);
   10044           61 :     case EXEC_OMP_PARALLEL_MASKED:
   10045           61 :     case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
   10046           61 :     case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
   10047           61 :     case EXEC_OMP_PARALLEL_MASTER:
   10048           61 :     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
   10049           61 :     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
   10050           61 :       return gfc_trans_omp_parallel_master_masked (code);
   10051           54 :     case EXEC_OMP_PARALLEL_SECTIONS:
   10052           54 :       return gfc_trans_omp_parallel_sections (code);
   10053           50 :     case EXEC_OMP_PARALLEL_WORKSHARE:
   10054           50 :       return gfc_trans_omp_parallel_workshare (code);
   10055           53 :     case EXEC_OMP_SCOPE:
   10056           53 :       return gfc_trans_omp_scope (code);
   10057           75 :     case EXEC_OMP_SECTIONS:
   10058           75 :       return gfc_trans_omp_sections (code, code->ext.omp_clauses);
   10059          556 :     case EXEC_OMP_SINGLE:
   10060          556 :       return gfc_trans_omp_single (code, code->ext.omp_clauses);
   10061         2369 :     case EXEC_OMP_TARGET:
   10062         2369 :     case EXEC_OMP_TARGET_PARALLEL:
   10063         2369 :     case EXEC_OMP_TARGET_PARALLEL_DO:
   10064         2369 :     case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
   10065         2369 :     case EXEC_OMP_TARGET_PARALLEL_LOOP:
   10066         2369 :     case EXEC_OMP_TARGET_SIMD:
   10067         2369 :     case EXEC_OMP_TARGET_TEAMS:
   10068         2369 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
   10069         2369 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
   10070         2369 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
   10071         2369 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
   10072         2369 :     case EXEC_OMP_TARGET_TEAMS_LOOP:
   10073         2369 :       return gfc_trans_omp_target (code);
   10074         1389 :     case EXEC_OMP_TARGET_DATA:
   10075         1389 :       return gfc_trans_omp_target_data (code);
   10076          437 :     case EXEC_OMP_TARGET_ENTER_DATA:
   10077          437 :       return gfc_trans_omp_target_enter_data (code);
   10078          361 :     case EXEC_OMP_TARGET_EXIT_DATA:
   10079          361 :       return gfc_trans_omp_target_exit_data (code);
   10080         1708 :     case EXEC_OMP_TARGET_UPDATE:
   10081         1708 :       return gfc_trans_omp_target_update (code);
   10082         1123 :     case EXEC_OMP_TASK:
   10083         1123 :       return gfc_trans_omp_task (code);
   10084          181 :     case EXEC_OMP_TASKGROUP:
   10085          181 :       return gfc_trans_omp_taskgroup (code);
   10086           31 :     case EXEC_OMP_TASKLOOP_SIMD:
   10087           31 :       return gfc_trans_omp_taskloop (code, code->op);
   10088          146 :     case EXEC_OMP_TASKWAIT:
   10089          146 :       return gfc_trans_omp_taskwait (code);
   10090            8 :     case EXEC_OMP_TASKYIELD:
   10091            8 :       return gfc_trans_omp_taskyield ();
   10092          290 :     case EXEC_OMP_TEAMS:
   10093          290 :     case EXEC_OMP_TEAMS_DISTRIBUTE:
   10094          290 :     case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
   10095          290 :     case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
   10096          290 :     case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
   10097          290 :     case EXEC_OMP_TEAMS_LOOP:
   10098          290 :       return gfc_trans_omp_teams (code, NULL, NULL_TREE);
   10099           35 :     case EXEC_OMP_WORKSHARE:
   10100           35 :       return gfc_trans_omp_workshare (code, code->ext.omp_clauses);
   10101            8 :     case EXEC_OMP_INTEROP:
   10102            8 :       return gfc_trans_openmp_interop (code, code->ext.omp_clauses);
   10103            0 :     default:
   10104            0 :       gcc_unreachable ();
   10105              :     }
   10106              : }
   10107              : 
   10108              : void
   10109          109 : gfc_trans_omp_declare_simd (gfc_namespace *ns)
   10110              : {
   10111          109 :   if (ns->entries)
   10112              :     return;
   10113              : 
   10114          109 :   gfc_omp_declare_simd *ods;
   10115          262 :   for (ods = ns->omp_declare_simd; ods; ods = ods->next)
   10116              :     {
   10117          153 :       tree c = gfc_trans_omp_clauses (NULL, ods->clauses, ods->where, true);
   10118          153 :       tree fndecl = ns->proc_name->backend_decl;
   10119          153 :       if (c != NULL_TREE)
   10120          103 :         c = tree_cons (NULL_TREE, c, NULL_TREE);
   10121          153 :       c = build_tree_list (get_identifier ("omp declare simd"), c);
   10122          153 :       TREE_CHAIN (c) = DECL_ATTRIBUTES (fndecl);
   10123          153 :       DECL_ATTRIBUTES (fndecl) = c;
   10124              :     }
   10125              : }
   10126              : 
   10127              : /* Translate the context selector list GFC_SELECTORS, using WHERE as the
   10128              :    locus for error messages.  */
   10129              : 
   10130              : static tree
   10131          513 : gfc_trans_omp_set_selector (gfc_omp_set_selector *gfc_selectors, locus where)
   10132              : {
   10133          513 :   tree set_selectors = NULL_TREE;
   10134          513 :   gfc_omp_set_selector *oss;
   10135              : 
   10136         1004 :   for (oss = gfc_selectors; oss; oss = oss->next)
   10137              :     {
   10138          491 :       tree selectors = NULL_TREE;
   10139          491 :       gfc_omp_selector *os;
   10140          491 :       enum omp_tss_code set = oss->code;
   10141          491 :       gcc_assert (set != OMP_TRAIT_SET_INVALID);
   10142              : 
   10143         1107 :       for (os = oss->trait_selectors; os; os = os->next)
   10144              :         {
   10145          616 :           tree scoreval = NULL_TREE;
   10146          616 :           tree properties = NULL_TREE;
   10147          616 :           gfc_omp_trait_property *otp;
   10148          616 :           enum omp_ts_code sel = os->code;
   10149              : 
   10150              :           /* Per the spec, "Implementations can ignore specified
   10151              :              selectors that are not those described in this section";
   10152              :              however, we  must record such selectors because they
   10153              :              cause match failures.  */
   10154          616 :           if (sel == OMP_TRAIT_INVALID)
   10155              :             {
   10156            1 :               selectors = make_trait_selector (sel, NULL_TREE, NULL_TREE,
   10157              :                                                selectors);
   10158            1 :               continue;
   10159              :             }
   10160              : 
   10161          987 :           for (otp = os->properties; otp; otp = otp->next)
   10162              :             {
   10163          372 :               switch (otp->property_kind)
   10164              :                 {
   10165           85 :                 case OMP_TRAIT_PROPERTY_DEV_NUM_EXPR:
   10166           85 :                 case OMP_TRAIT_PROPERTY_BOOL_EXPR:
   10167           85 :                   {
   10168           85 :                     tree expr = NULL_TREE;
   10169           85 :                     gfc_se se;
   10170           85 :                     gfc_init_se (&se, NULL);
   10171           85 :                     gfc_conv_expr (&se, otp->expr);
   10172           85 :                     expr = se.expr;
   10173           85 :                     properties = make_trait_property (NULL_TREE, expr,
   10174              :                                                       properties);
   10175              :                   }
   10176           85 :                   break;
   10177           23 :                 case OMP_TRAIT_PROPERTY_ID:
   10178           23 :                   properties
   10179           23 :                     = make_trait_property (get_identifier (otp->name),
   10180              :                                            NULL_TREE, properties);
   10181           23 :                   break;
   10182          250 :                 case OMP_TRAIT_PROPERTY_NAME_LIST:
   10183          250 :                   {
   10184          250 :                     tree prop = OMP_TP_NAMELIST_NODE;
   10185          250 :                     tree value = NULL_TREE;
   10186          250 :                     if (otp->is_name)
   10187          165 :                       value = get_identifier (otp->name);
   10188              :                     else
   10189           85 :                       value = gfc_conv_constant_to_tree (otp->expr);
   10190              : 
   10191          250 :                     properties = make_trait_property (prop, value,
   10192              :                                                       properties);
   10193              :                   }
   10194          250 :                   break;
   10195           14 :                 case OMP_TRAIT_PROPERTY_CLAUSE_LIST:
   10196           14 :                   properties = gfc_trans_omp_clauses (NULL, otp->clauses,
   10197              :                                                       where, true);
   10198           14 :                   break;
   10199            0 :                 default:
   10200            0 :                   gcc_unreachable ();
   10201              :                 }
   10202              :             }
   10203              : 
   10204          615 :           if (os->score)
   10205              :             {
   10206           51 :               gfc_se se;
   10207           51 :               gfc_init_se (&se, NULL);
   10208           51 :               gfc_conv_expr (&se, os->score);
   10209           51 :               scoreval = se.expr;
   10210              :             }
   10211              : 
   10212          615 :           selectors = make_trait_selector (sel, scoreval,
   10213              :                                            properties, selectors);
   10214              :         }
   10215          491 :       set_selectors = make_trait_set_selector (set, selectors, set_selectors);
   10216              :     }
   10217          513 :   return set_selectors;
   10218              : }
   10219              : 
   10220              : /* If 'ns' points to a formal namespace in an interface, ns->parent == NULL;
   10221              :    hence, parent_ns is used instead.  */
   10222              : 
   10223              : void
   10224        10685 : gfc_trans_omp_declare_variant (gfc_namespace *ns, gfc_namespace *parent_ns)
   10225              : {
   10226        10685 :   tree base_fn_decl = ns->proc_name->backend_decl;
   10227        10685 :   gfc_namespace *search_ns = ns;
   10228        10685 :   gfc_omp_declare_variant *next;
   10229              : 
   10230        10685 :   for (gfc_omp_declare_variant *odv = search_ns->omp_declare_variant;
   10231        28988 :        search_ns; odv = next)
   10232              :     {
   10233              :       /* Look in the parent namespace if there are no more directives in the
   10234              :          current namespace.  */
   10235        18303 :       if (!odv)
   10236              :         {
   10237        17918 :           if (!search_ns->parent && search_ns == ns)
   10238              :             search_ns = parent_ns;
   10239              :           else
   10240        12574 :             search_ns = search_ns->parent;
   10241        17918 :           if (search_ns)
   10242         7233 :             next = search_ns->omp_declare_variant;
   10243        17918 :           continue;
   10244              :         }
   10245              : 
   10246          385 :       next = odv->next;
   10247              : 
   10248          385 :       if (odv->error_p)
   10249           17 :         continue;
   10250              : 
   10251              :       /* Check directive the first time it is encountered.  */
   10252          368 :       bool error_found = true;
   10253              : 
   10254          368 :       if (odv->checked_p)
   10255           43 :         error_found = false;
   10256          368 :       if (odv->base_proc_symtree == NULL)
   10257              :         {
   10258          331 :           if (!search_ns->proc_name->attr.function
   10259          212 :               && !search_ns->proc_name->attr.subroutine)
   10260            1 :             gfc_error ("The base name for %<declare variant%> must be "
   10261              :                        "specified at %L", &odv->where);
   10262              :           else
   10263              :             error_found = false;
   10264              :         }
   10265              :       else
   10266              :         {
   10267           37 :           if (!search_ns->contained
   10268           21 :               && !odv->base_proc_symtree->n.sym->attr.use_assoc
   10269            5 :               && strcmp (odv->base_proc_symtree->name,
   10270            5 :                          ns->proc_name->name))
   10271            1 :             gfc_error ("The base name at %L does not match the name of the "
   10272              :                        "current procedure", &odv->where);
   10273           36 :           else if (odv->base_proc_symtree->n.sym->attr.entry)
   10274            1 :             gfc_error ("The base name at %L must not be an entry name",
   10275              :                         &odv->where);
   10276           35 :           else if (odv->base_proc_symtree->n.sym->attr.generic)
   10277            1 :             gfc_error ("The base name at %L must not be a generic name",
   10278              :                         &odv->where);
   10279           34 :           else if (odv->base_proc_symtree->n.sym->attr.proc_pointer)
   10280            1 :             gfc_error ("The base name at %L must not be a procedure pointer",
   10281              :                         &odv->where);
   10282           33 :           else if (odv->base_proc_symtree->n.sym->attr.implicit_type)
   10283            1 :             gfc_error ("The base procedure at %L must have an explicit "
   10284              :                         "interface", &odv->where);
   10285              :           else
   10286              :             error_found = false;
   10287              :         }
   10288              : 
   10289          368 :       odv->checked_p = true;
   10290          368 :       if (error_found)
   10291              :         {
   10292            6 :           odv->error_p = true;
   10293            6 :           continue;
   10294              :         }
   10295              : 
   10296              :       /* Ignore directives that do not apply to the current procedure.  */
   10297          362 :       if ((odv->base_proc_symtree == NULL && search_ns != ns)
   10298          336 :           || (odv->base_proc_symtree != NULL
   10299           32 :               && !ns->proc_name->attr.use_assoc
   10300           19 :               && strcmp (odv->base_proc_symtree->name, ns->proc_name->name))
   10301          323 :           || (odv->base_proc_symtree != NULL
   10302           19 :               && ns->proc_name->attr.use_assoc
   10303           13 :               && strcmp (odv->base_proc_symtree->n.sym->name,
   10304              :                          ns->proc_name->name)))
   10305           44 :         continue;
   10306              : 
   10307          318 :       tree set_selectors = gfc_trans_omp_set_selector (odv->set_selectors,
   10308              :                                                        odv->where);
   10309          318 :       const char *variant_proc_name = odv->variant_proc_symtree->name;
   10310          318 :       gfc_symbol *variant_proc_sym = odv->variant_proc_symtree->n.sym;
   10311          318 :       if (variant_proc_sym == NULL || variant_proc_sym->attr.implicit_type)
   10312              :         {
   10313           39 :           gfc_symtree *proc_st;
   10314           39 :           gfc_find_sym_tree (variant_proc_name, gfc_current_ns, 1, &proc_st);
   10315           39 :           variant_proc_sym = proc_st ? proc_st->n.sym : NULL;
   10316              :         }
   10317           39 :       if (variant_proc_sym == NULL)
   10318              :         {
   10319            1 :           gfc_error ("Cannot find symbol %qs at %L", variant_proc_name,
   10320              :                                                      &odv->where);
   10321            1 :           continue;
   10322              :         }
   10323          317 :       set_selectors = omp_check_context_selector
   10324          317 :         (gfc_get_location (&odv->where), set_selectors,
   10325              :          OMP_CTX_DECLARE_VARIANT);
   10326          317 :       if (set_selectors != error_mark_node)
   10327              :         {
   10328          297 :           if (!variant_proc_sym->attr.implicit_type
   10329          297 :               && !variant_proc_sym->attr.subroutine
   10330           89 :               && !variant_proc_sym->attr.function)
   10331              :             {
   10332            0 :               gfc_error ("variant %qs at %L is not a function or subroutine",
   10333              :                          variant_proc_name, &odv->where);
   10334            0 :               variant_proc_sym = NULL;
   10335              :             }
   10336          297 :           else if (variant_proc_sym == ns->proc_name)
   10337              :             {
   10338            1 :               gfc_error ("variant %qs at %L is the same as base function",
   10339              :                          variant_proc_name, &odv->where);
   10340            1 :               variant_proc_sym = NULL;
   10341              :             }
   10342          296 :           else if (omp_get_context_selector (set_selectors,
   10343              :                                              OMP_TRAIT_SET_CONSTRUCT,
   10344              :                                              OMP_TRAIT_CONSTRUCT_SIMD)
   10345              :                    == NULL_TREE)
   10346              :             {
   10347          282 :               char err[256];
   10348          282 :               gfc_formal_arglist *last_arg = NULL, *extra_arg = NULL;
   10349          282 :               int nappend_args = 0;
   10350          282 :               if (odv->append_args_list)
   10351              :                 {
   10352           26 :                   gfc_formal_arglist *arg;
   10353           26 :                   int nargs = 0;
   10354           26 :                   for (arg = gfc_sym_get_dummy_args (ns->proc_name);
   10355           56 :                        arg; arg = arg->next)
   10356           30 :                     nargs++;
   10357              : 
   10358           26 :                   last_arg = gfc_sym_get_dummy_args (variant_proc_sym);
   10359           33 :                   for (int i = 1 ; i < nargs && last_arg; i++)
   10360            7 :                     last_arg = last_arg->next;
   10361           26 :                   if (nargs == 0)
   10362              :                     {
   10363            3 :                       extra_arg = last_arg;
   10364            3 :                       last_arg = NULL;
   10365            3 :                       variant_proc_sym->formal = NULL;
   10366              :                     }
   10367           23 :                   else if (last_arg)
   10368              :                     {
   10369           23 :                       extra_arg = last_arg->next;
   10370           23 :                       last_arg->next = NULL;
   10371              :                     }
   10372           76 :                   for (gfc_omp_namelist *n = odv->append_args_list; n != NULL;
   10373           50 :                        n = n->next)
   10374           50 :                     nappend_args++;
   10375              :                 }
   10376          282 :               if (!gfc_compare_interfaces (ns->proc_name, variant_proc_sym,
   10377              :                                            variant_proc_sym->name, 0, 1,
   10378              :                                            err, sizeof (err), NULL, NULL))
   10379              :                 {
   10380            2 :                   gfc_error ("variant %qs and base %qs at %L have "
   10381              :                              "incompatible types: %s",
   10382            2 :                              variant_proc_name, ns->proc_name->name,
   10383              :                              &odv->where, err);
   10384            2 :                   if (nappend_args)
   10385            0 :                     inform (gfc_get_location (&odv->append_args_list->where),
   10386              :                             "%<append_args%> clause implies that %qs has %d "
   10387              :                             "dummy arguments of integer type with "
   10388              :                             "%<omp_interop_kind%> kind", variant_proc_name,
   10389              :                             nappend_args);
   10390              :                   variant_proc_sym = NULL;
   10391              :                 }
   10392          282 :               if (last_arg)
   10393           23 :                 last_arg->next = extra_arg;
   10394          259 :               else if (extra_arg)
   10395            3 :                 variant_proc_sym->formal = extra_arg;
   10396           26 :               locus *loc = (odv->append_args_list
   10397          282 :                             ? &odv->append_args_list->where :  &odv->where);
   10398          282 :               int nextra_arg = 0;
   10399          335 :               for (; extra_arg; extra_arg = extra_arg->next)
   10400              :                 {
   10401           53 :                   nextra_arg++;
   10402           53 :                   if (!variant_proc_sym)
   10403            8 :                     continue;
   10404           45 :                   if (extra_arg->sym->ts.type != BT_INTEGER
   10405           43 :                       || extra_arg->sym->ts.kind != gfc_index_integer_kind
   10406           42 :                       || extra_arg->sym->attr.dimension
   10407           40 :                       || extra_arg->sym->attr.codimension
   10408           39 :                       || extra_arg->sym->attr.pointer
   10409           38 :                       || extra_arg->sym->attr.allocatable
   10410           37 :                       || extra_arg->sym->attr.proc_pointer)
   10411              :                     {
   10412            8 :                       gfc_error ("%qs at %L must be a nonpointer, "
   10413              :                                  "nonallocatable scalar integer dummy argument "
   10414              :                                  "of %<omp_interop_kind%> kind as it utilized "
   10415              :                                  "with the %<append_args%> clause at %L",
   10416              :                                  extra_arg->sym->name,
   10417              :                                  &extra_arg->sym->declared_at, loc);
   10418            8 :                       variant_proc_sym = NULL;
   10419              :                     }
   10420           45 :                   if (extra_arg->sym->attr.optional)
   10421              :                     {
   10422            2 :                       gfc_error ("%qs at %L with OPTIONAL attribute "
   10423              :                                  "not support when utilized with the "
   10424              :                                  "%<append_args%> clause at %L",
   10425              :                                  extra_arg->sym->name,
   10426              :                                  &extra_arg->sym->declared_at, loc);
   10427            2 :                       variant_proc_sym = NULL;
   10428              :                     }
   10429              :                 }
   10430          282 :               if (variant_proc_sym && nappend_args != nextra_arg)
   10431              :                 {
   10432            1 :                   gfc_error ("%qs at %L has %d but requires %d "
   10433              :                              "%<omp_interop_kind%> kind dummy arguments as it "
   10434              :                              "is utilized with the %<append_args%> clause at "
   10435              :                              "%L", variant_proc_sym->name,
   10436              :                              &variant_proc_sym->declared_at, nextra_arg,
   10437              :                              nappend_args, loc);
   10438            1 :                   variant_proc_sym = NULL;
   10439              :                 }
   10440              :             }
   10441          251 :           if ((odv->adjust_args_list != NULL || odv->append_args_list != NULL)
   10442          322 :               && omp_get_context_selector (set_selectors,
   10443              :                                            OMP_TRAIT_SET_CONSTRUCT,
   10444              :                                            OMP_TRAIT_CONSTRUCT_DISPATCH)
   10445              :                    == NULL_TREE)
   10446              :             {
   10447            6 :               gfc_error ("the %qs clause can only be specified if "
   10448              :                          "the %<dispatch%> selector of the construct "
   10449              :                          "selector set appears in the %<match%> clause at %L",
   10450            3 :                          odv->adjust_args_list ? "adjust_args" : "append_args",
   10451              :                          &odv->where);
   10452            3 :               variant_proc_sym = NULL;
   10453              :             }
   10454          297 :           if (variant_proc_sym != NULL)
   10455              :             {
   10456          281 :               gfc_set_sym_referenced (variant_proc_sym);
   10457          281 :               tree construct
   10458          281 :                 = omp_get_context_selector_list (set_selectors,
   10459              :                                                  OMP_TRAIT_SET_CONSTRUCT);
   10460          281 :               omp_mark_declare_variant (gfc_get_location (&odv->where),
   10461              :                                         gfc_get_symbol_decl (variant_proc_sym),
   10462              :                                         construct);
   10463          281 :               if (omp_context_selector_matches (set_selectors,
   10464              :                                                 NULL_TREE, false))
   10465              :                 {
   10466          202 :                   tree need_device_ptr_list = NULL_TREE;
   10467          202 :                   tree need_device_addr_list = NULL_TREE;
   10468          202 :                   tree append_args_tree = NULL_TREE;
   10469          202 :                   tree id = get_identifier ("omp declare variant base");
   10470          202 :                   tree variant = gfc_get_symbol_decl (variant_proc_sym);
   10471          202 :                   DECL_ATTRIBUTES (base_fn_decl)
   10472          202 :                     = tree_cons (id, build_tree_list (variant, set_selectors),
   10473          202 :                                  DECL_ATTRIBUTES (base_fn_decl));
   10474          202 :                   int arg_idx_offset = 0;
   10475          202 :                   if (gfc_return_by_reference (ns->proc_name))
   10476              :                     {
   10477            2 :                       arg_idx_offset++;
   10478            2 :                       if (ns->proc_name->ts.type == BT_CHARACTER)
   10479            2 :                         arg_idx_offset++;
   10480              :                     }
   10481          202 :                   int nargs = 0;
   10482          202 :                   for (gfc_formal_arglist *arg
   10483          202 :                         = gfc_sym_get_dummy_args (ns->proc_name);
   10484          443 :                        arg; arg = arg->next)
   10485          241 :                     nargs++;
   10486          202 :                   if (odv->append_args_list)
   10487              :                     {
   10488           14 :                       int append_arg_no = arg_idx_offset + nargs;
   10489           14 :                       tree last_arg = NULL_TREE;
   10490           14 :                       for (gfc_omp_namelist *n = odv->append_args_list;
   10491           43 :                            n != NULL; n = n->next)
   10492              :                         {
   10493           29 :                           tree pref = NULL_TREE;
   10494           29 :                           if (n->u.init.len)
   10495              :                             {
   10496           22 :                               pref = build_string (n->u.init.len,
   10497           11 :                                                    n->u2.init_interop);
   10498           11 :                               TREE_TYPE (pref) = build_array_type_nelts (
   10499              :                                                    unsigned_char_type_node,
   10500           11 :                                                    n->u.init.len);
   10501              :                             }
   10502              :                           /* Save location, (target + target sync) and
   10503              :                              prefer_type list in a tree list.  */
   10504           29 :                           tree t = build_tree_list (n->u.init.target
   10505              :                                                     ? boolean_true_node
   10506              :                                                     : boolean_false_node,
   10507           29 :                                                     n->u.init.targetsync
   10508              :                                                     ? boolean_true_node
   10509              :                                                     : boolean_false_node);
   10510           29 :                           t = build1_loc (gfc_get_location (&n->where),
   10511              :                                           NOP_EXPR, void_type_node, t);
   10512           29 :                           t = build_tree_list (t, pref);
   10513           29 :                           if (append_args_tree)
   10514              :                             {
   10515           15 :                               TREE_CHAIN (last_arg) = t;
   10516           15 :                               last_arg = t;
   10517              :                             }
   10518              :                           else
   10519              :                             append_args_tree = last_arg = t;
   10520              :                         }
   10521              :                       /* Store as 'purpose' = arg number to be used for inserting
   10522              :                          and 'value' = list of interop items.  */
   10523           14 :                       append_args_tree = build_tree_list (
   10524              :                                            build_int_cst (integer_type_node,
   10525           14 :                                                           append_arg_no),
   10526              :                                            append_args_tree);
   10527              :                     }
   10528          202 :                   vec<gfc_symbol *> adjust_args_list = vNULL;
   10529          202 :                   for (gfc_omp_namelist *arg_list = odv->adjust_args_list;
   10530          312 :                        arg_list != NULL; arg_list = arg_list->next)
   10531              :                     {
   10532          110 :                       int from, to;
   10533          110 :                       if (arg_list->expr == NULL || arg_list->sym)
   10534          204 :                         from = ((arg_list->u.adj_args.omp_num_args_minus
   10535           94 :                                  || arg_list->u.adj_args.omp_num_args_plus)
   10536           94 :                                 ? nargs : 1);
   10537              :                       else
   10538              :                         {
   10539           16 :                           if (arg_list->u.adj_args.omp_num_args_plus)
   10540            0 :                             mpz_add_ui (arg_list->expr->value.integer,
   10541            0 :                                         arg_list->expr->value.integer, nargs);
   10542           16 :                           if (arg_list->u.adj_args.omp_num_args_minus)
   10543            2 :                             mpz_ui_sub (arg_list->expr->value.integer, nargs,
   10544            2 :                                         arg_list->expr->value.integer);
   10545           16 :                           if (mpz_sgn (arg_list->expr->value.integer) <= 0)
   10546              :                             {
   10547            1 :                               gfc_warning (OPT_Wopenmp,
   10548              :                                            "Expected positive argument index "
   10549              :                                            "at %L", &arg_list->where);
   10550            1 :                               from = 1;
   10551              :                             }
   10552              :                           else
   10553           15 :                             from
   10554           15 :                               = (mpz_fits_sint_p (arg_list->expr->value.integer)
   10555           15 :                                  ? mpz_get_si (arg_list->expr->value.integer)
   10556              :                                  : INT_MAX);
   10557           16 :                           if (from > nargs)
   10558            1 :                             gfc_warning (OPT_Wopenmp,
   10559              :                                          "Argument index at %L exceeds number "
   10560              :                                          "of arguments %d", &arg_list->where,
   10561              :                                          nargs);
   10562              :                         }
   10563          110 :                       locus loc = arg_list->where;
   10564          110 :                       if (!arg_list->u.adj_args.range_start)
   10565              :                         to = from;
   10566              :                       else
   10567              :                         {
   10568            6 :                           loc = gfc_get_location_range (&arg_list->where, 0,
   10569              :                                                         &arg_list->where, 0,
   10570            6 :                                                         &arg_list->next->where);
   10571            6 :                           if (arg_list->next->expr == NULL)
   10572              :                             to = nargs;
   10573              :                           else
   10574              :                             {
   10575            4 :                               if (arg_list->next->u.adj_args.omp_num_args_plus)
   10576            0 :                                 mpz_add_ui (arg_list->next->expr->value.integer,
   10577            0 :                                             arg_list->next->expr->value.integer,
   10578              :                                             nargs);
   10579            4 :                               if (arg_list->next->u.adj_args.omp_num_args_minus)
   10580            2 :                                 mpz_ui_sub (arg_list->next->expr->value.integer,
   10581              :                                             nargs,
   10582            2 :                                             arg_list->next->expr->value.integer);
   10583            4 :                               if (mpz_sgn (arg_list->next->expr->value.integer)
   10584              :                                   <= 0)
   10585              :                                 {
   10586            0 :                                   gfc_warning (OPT_Wopenmp,
   10587              :                                                "Expected positive argument "
   10588              :                                                "index at %L", &loc);
   10589            0 :                                   to = 0;
   10590              :                                 }
   10591              :                               else
   10592            4 :                                 to = mpz_get_si (
   10593            4 :                                        arg_list->next->expr->value.integer);
   10594              :                             }
   10595            6 :                           if (from > to && to != 0)
   10596            1 :                             gfc_warning (OPT_Wopenmp,
   10597              :                                          "Upper argument index smaller than "
   10598              :                                          "lower one at %L", &loc);
   10599            6 :                           if (to > nargs)
   10600              :                             to = nargs;
   10601            6 :                           arg_list = arg_list->next;
   10602              :                         }
   10603          110 :                       if (from > nargs)
   10604            1 :                         continue;
   10605              :                       /* Change to zero based index.  */
   10606          109 :                       from--; to--;
   10607          109 :                       gfc_formal_arglist *arg = ns->proc_name->formal;
   10608          109 :                       if (!arg_list->sym && to >= from)
   10609           35 :                         for (int idx = 0; idx < from; idx++)
   10610           18 :                           arg = arg->next;
   10611          223 :                       for (int idx = from; idx <= to; idx++)
   10612              :                         {
   10613          114 :                           if (idx > from)
   10614            6 :                             arg = arg->next;
   10615          114 :                           if (arg_list->sym)
   10616              :                             {
   10617           91 :                               for (arg = ns->proc_name->formal, idx = 0;
   10618          201 :                                    arg != NULL; arg = arg->next, idx++)
   10619          200 :                                 if (arg->sym == arg_list->sym)
   10620              :                                   break;
   10621           91 :                               if (!arg || !arg_list->sym->attr.dummy)
   10622              :                                 {
   10623            1 :                                   gfc_error ("List item %qs at %L, declared at "
   10624              :                                              "%L, is not a dummy argument",
   10625              :                                              arg_list->sym->name, &loc,
   10626              :                                              &arg_list->sym->declared_at);
   10627            1 :                                   continue;
   10628              :                                 }
   10629              :                             }
   10630          113 :                           if (arg_list->u.adj_args.need_ptr
   10631           82 :                               && (arg->sym->ts.f90_type != BT_VOID
   10632           80 :                                   || !arg->sym->ts.u.derived->ts.is_iso_c
   10633           80 :                                   || (arg->sym->ts.u.derived->intmod_sym_id
   10634              :                                       != ISOCBINDING_PTR)
   10635           79 :                                   || arg->sym->attr.dimension))
   10636              :                             {
   10637            6 :                               gfc_error ("Argument %qs at %L to list item in "
   10638              :                                          "%<need_device_ptr%> at %L must be a "
   10639              :                                          "scalar of TYPE(C_PTR)",
   10640              :                                          arg->sym->name,
   10641              :                                          &arg->sym->declared_at, &loc);
   10642            6 :                               if (!arg->sym->attr.value)
   10643            6 :                                 inform (gfc_get_location (&loc),
   10644              :                                         "Consider using %<need_device_addr%> "
   10645              :                                         "instead");
   10646            6 :                               continue;
   10647              :                             }
   10648          107 :                           if (arg_list->u.adj_args.need_addr
   10649           11 :                               && arg->sym->attr.value)
   10650              :                             {
   10651            1 :                               gfc_error ("Argument %qs at %L to list item in "
   10652              :                                          "%<need_device_addr%> at %L must not "
   10653              :                                          "have the VALUE attribute",
   10654              :                                          arg->sym->name,
   10655              :                                          &arg->sym->declared_at, &loc);
   10656            1 :                               continue;
   10657              :                             }
   10658          106 :                           if (adjust_args_list.contains (arg->sym))
   10659              :                             {
   10660            7 :                               gfc_error ("%qs at %L is specified more than "
   10661            7 :                                          "once", arg->sym->name, &loc);
   10662            7 :                               continue;
   10663              :                             }
   10664           99 :                           adjust_args_list.safe_push (arg->sym);
   10665              : 
   10666           99 :                           if (arg_list->u.adj_args.need_addr)
   10667              :                             {
   10668              :                               /* TODO: Has to to support OPTIONAL and array
   10669              :                                  descriptors; should check for CLASS, coarrays?
   10670              :                                  Reject "abc" and 123 as actual arguments (in
   10671              :                                  gimplify.cc or in the FE? Reject noncontiguous
   10672              :                                  actuals?  Cf. also PR C++/118859.
   10673              :                                  Also check array-valued type(c_ptr).  */
   10674            7 :                               static bool warned = false;
   10675            7 :                               if (!warned)
   10676            1 :                                 sorry_at (gfc_get_location (&loc),
   10677              :                                           "%<need_device_addr%> not yet "
   10678              :                                           "supported");
   10679            7 :                               warned = true;
   10680            7 :                               continue;
   10681            7 :                             }
   10682           92 :                           if (arg_list->u.adj_args.need_ptr
   10683              :                               || arg_list->u.adj_args.need_addr)
   10684              :                             {
   10685              :                               // Store 0-based argument index,
   10686              :                               // as in gimplify_call_expr
   10687           74 :                               tree t
   10688           74 :                                 = build_tree_list (
   10689              :                                     NULL_TREE,
   10690              :                                     build_int_cst (integer_type_node,
   10691           74 :                                                    idx + arg_idx_offset));
   10692           74 :                               if (arg_list->u.adj_args.need_ptr)
   10693           74 :                                 need_device_ptr_list
   10694           74 :                                   = chainon (need_device_ptr_list, t);
   10695              :                               else
   10696            0 :                                 need_device_addr_list
   10697            0 :                                   = chainon (need_device_addr_list, t);
   10698              :                             }
   10699              :                         }
   10700              :                     }
   10701          202 :                   tree t = NULL_TREE;
   10702          202 :                   if (need_device_ptr_list
   10703          202 :                       || need_device_addr_list
   10704          166 :                       || append_args_tree)
   10705              :                     {
   10706           50 :                       t = build_tree_list (need_device_ptr_list,
   10707              :                                            need_device_addr_list),
   10708           50 :                       TREE_CHAIN (t) = append_args_tree;
   10709           50 :                       DECL_ATTRIBUTES (variant) = tree_cons (
   10710              :                         get_identifier ("omp declare variant variant args"), t,
   10711           50 :                         DECL_ATTRIBUTES (variant));
   10712              :                     }
   10713              :                 }
   10714              :             }
   10715              :         }
   10716              :     }
   10717        10685 : }
   10718              : 
   10719              : /* Add ptr for tracking as being allocated by GOMP_alloc. */
   10720              : 
   10721              : tree
   10722           29 : gfc_omp_call_add_alloc (tree ptr)
   10723              : {
   10724           29 :   static tree fn = NULL_TREE;
   10725           29 :   if (fn == NULL_TREE)
   10726              :     {
   10727            6 :       fn = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
   10728            6 :       tree att = build_tree_list (NULL_TREE, build_string (4, ". R "));
   10729            6 :       att = tree_cons (get_identifier ("fn spec"), att, TYPE_ATTRIBUTES (fn));
   10730            6 :       fn = build_type_attribute_variant (fn, att);
   10731            6 :       fn = build_fn_decl ("GOMP_add_alloc", fn);
   10732              :     }
   10733           29 :   return build_call_expr_loc (input_location, fn, 1, ptr);
   10734              : }
   10735              : 
   10736              : /* Generated function returns true when it was tracked via GOMP_add_alloc and
   10737              :    removes it from the tracking.  As called just before GOMP_free or omp_realloc
   10738              :    the pointer is or might become invalid, thus, it is always removed. */
   10739              : 
   10740              : tree
   10741           47 : gfc_omp_call_is_alloc (tree ptr)
   10742              : {
   10743           47 :   static tree fn = NULL_TREE;
   10744           47 :   if (fn == NULL_TREE)
   10745              :     {
   10746            6 :       fn = build_function_type_list (boolean_type_node, ptr_type_node,
   10747              :                                      NULL_TREE);
   10748            6 :       tree att = build_tree_list (NULL_TREE, build_string (4, ". R "));
   10749            6 :       att = tree_cons (get_identifier ("fn spec"), att, TYPE_ATTRIBUTES (fn));
   10750            6 :       fn = build_type_attribute_variant (fn, att);
   10751            6 :       fn = build_fn_decl ("GOMP_is_alloc", fn);
   10752              :     }
   10753           47 :   return build_call_expr_loc (input_location, fn, 1, ptr);
   10754              : }
   10755              : 
   10756              : tree
   10757           88 : gfc_trans_omp_metadirective (gfc_code *code)
   10758              : {
   10759           88 :   gfc_omp_variant *variant = code->ext.omp_variants;
   10760              : 
   10761           88 :   tree metadirective_tree = make_node (OMP_METADIRECTIVE);
   10762           88 :   SET_EXPR_LOCATION (metadirective_tree, gfc_get_location (&code->loc));
   10763           88 :   TREE_TYPE (metadirective_tree) = void_type_node;
   10764           88 :   OMP_METADIRECTIVE_VARIANTS (metadirective_tree) = NULL_TREE;
   10765              : 
   10766           88 :   tree tree_body = NULL_TREE;
   10767              : 
   10768          283 :   while (variant)
   10769              :     {
   10770          195 :       tree ctx = gfc_trans_omp_set_selector (variant->selectors,
   10771              :                                              variant->where);
   10772          195 :       ctx = omp_check_context_selector (gfc_get_location (&variant->where),
   10773              :                                         ctx, OMP_CTX_METADIRECTIVE);
   10774          195 :       if (ctx == error_mark_node)
   10775              :         return error_mark_node;
   10776              : 
   10777              :       /* If the selector doesn't match, drop the whole variant.  */
   10778          195 :       if (!omp_context_selector_matches (ctx, NULL_TREE, false))
   10779              :         {
   10780           23 :           variant = variant->next;
   10781           23 :           continue;
   10782              :         }
   10783              : 
   10784          172 :       gfc_code *next_code = variant->code->next;
   10785          172 :       if (next_code && tree_body == NULL_TREE)
   10786           18 :         tree_body = gfc_trans_code (next_code);
   10787              : 
   10788          172 :       if (next_code)
   10789           20 :         variant->code->next = NULL;
   10790          172 :       tree directive = gfc_trans_code (variant->code);
   10791          172 :       if (next_code)
   10792           20 :         variant->code->next = next_code;
   10793              : 
   10794           20 :       tree body = next_code ? tree_body : NULL_TREE;
   10795          172 :       tree omp_variant = make_omp_metadirective_variant (ctx, directive, body);
   10796          344 :       OMP_METADIRECTIVE_VARIANTS (metadirective_tree)
   10797          172 :         = chainon (OMP_METADIRECTIVE_VARIANTS (metadirective_tree),
   10798              :                    omp_variant);
   10799          172 :       variant = variant->next;
   10800              :     }
   10801              : 
   10802              :   /* TODO: Resolve the metadirective here if possible.   */
   10803              : 
   10804              :   return metadirective_tree;
   10805              : }
        

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.