LCOV - code coverage report
Current view: top level - gcc/fortran - trans-stmt.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 96.2 % 3885 3737
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 74 74
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Statement translation -- generate GCC trees from gfc_code.
       2              :    Copyright (C) 2002-2026 Free Software Foundation, Inc.
       3              :    Contributed by Paul Brook <paul@nowt.org>
       4              :    and Steven Bosscher <s.bosscher@student.tudelft.nl>
       5              : 
       6              : This file is part of GCC.
       7              : 
       8              : GCC is free software; you can redistribute it and/or modify it under
       9              : the terms of the GNU General Public License as published by the Free
      10              : Software Foundation; either version 3, or (at your option) any later
      11              : version.
      12              : 
      13              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      14              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      15              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      16              : for more details.
      17              : 
      18              : You should have received a copy of the GNU General Public License
      19              : along with GCC; see the file COPYING3.  If not see
      20              : <http://www.gnu.org/licenses/>.  */
      21              : 
      22              : #define INCLUDE_VECTOR
      23              : #include "config.h"
      24              : #include "system.h"
      25              : #include "coretypes.h"
      26              : #include "options.h"
      27              : #include "tree.h"
      28              : #include "gfortran.h"
      29              : #include "trans.h"
      30              : #include "stringpool.h"
      31              : #include "fold-const.h"
      32              : #include "trans-stmt.h"
      33              : #include "trans-types.h"
      34              : #include "trans-array.h"
      35              : #include "trans-const.h"
      36              : #include "dependency.h"
      37              : 
      38              : typedef struct iter_info
      39              : {
      40              :   tree var;
      41              :   tree start;
      42              :   tree end;
      43              :   tree step;
      44              :   gfc_loop_annot annot;
      45              :   struct iter_info *next;
      46              : }
      47              : iter_info;
      48              : 
      49              : typedef struct forall_info
      50              : {
      51              :   iter_info *this_loop;
      52              :   tree mask;
      53              :   tree maskindex;
      54              :   int nvar;
      55              :   tree size;
      56              :   struct forall_info  *prev_nest;
      57              :   bool do_concurrent;
      58              : }
      59              : forall_info;
      60              : 
      61              : static void gfc_trans_where_2 (gfc_code *, tree, bool,
      62              :                                forall_info *, stmtblock_t *);
      63              : 
      64              : /* Translate a F95 label number to a LABEL_EXPR.  */
      65              : 
      66              : tree
      67         3519 : gfc_trans_label_here (gfc_code * code)
      68              : {
      69         3519 :   return build1_v (LABEL_EXPR, gfc_get_label_decl (code->here));
      70              : }
      71              : 
      72              : 
      73              : /* Given a variable expression which has been ASSIGNed to, find the decl
      74              :    containing the auxiliary variables.  For variables in common blocks this
      75              :    is a field_decl.  */
      76              : 
      77              : void
      78          187 : gfc_conv_label_variable (gfc_se * se, gfc_expr * expr)
      79              : {
      80          187 :   gcc_assert (expr->symtree->n.sym->attr.assign == 1);
      81          187 :   gfc_conv_expr (se, expr);
      82              :   /* Deals with variable in common block. Get the field declaration.  */
      83          187 :   if (TREE_CODE (se->expr) == COMPONENT_REF)
      84            0 :     se->expr = TREE_OPERAND (se->expr, 1);
      85              :   /* Deals with dummy argument. Get the parameter declaration.  */
      86          187 :   else if (INDIRECT_REF_P (se->expr))
      87           12 :     se->expr = TREE_OPERAND (se->expr, 0);
      88          187 : }
      89              : 
      90              : /* Translate a label assignment statement.  */
      91              : 
      92              : tree
      93          116 : gfc_trans_label_assign (gfc_code * code)
      94              : {
      95          116 :   tree label_tree;
      96          116 :   gfc_se se;
      97          116 :   tree len;
      98          116 :   tree addr;
      99          116 :   tree len_tree;
     100          116 :   int label_len;
     101              : 
     102              :   /* Start a new block.  */
     103          116 :   gfc_init_se (&se, NULL);
     104          116 :   gfc_start_block (&se.pre);
     105          116 :   gfc_conv_label_variable (&se, code->expr1);
     106              : 
     107          116 :   len = GFC_DECL_STRING_LEN (se.expr);
     108          116 :   addr = GFC_DECL_ASSIGN_ADDR (se.expr);
     109              : 
     110          116 :   label_tree = gfc_get_label_decl (code->label1);
     111              : 
     112          116 :   if (code->label1->defined == ST_LABEL_TARGET
     113          116 :       || code->label1->defined == ST_LABEL_DO_TARGET)
     114              :     {
     115          115 :       label_tree = gfc_build_addr_expr (pvoid_type_node, label_tree);
     116          115 :       len_tree = build_int_cst (gfc_charlen_type_node, -1);
     117              :     }
     118              :   else
     119              :     {
     120            1 :       gfc_expr *format = code->label1->format;
     121              : 
     122            1 :       label_len = format->value.character.length;
     123            1 :       len_tree = build_int_cst (gfc_charlen_type_node, label_len);
     124            2 :       label_tree = gfc_build_wide_string_const (format->ts.kind, label_len + 1,
     125            1 :                                                 format->value.character.string);
     126            1 :       label_tree = gfc_build_addr_expr (pvoid_type_node, label_tree);
     127              :     }
     128              : 
     129          116 :   gfc_add_modify (&se.pre, len, fold_convert (TREE_TYPE (len), len_tree));
     130          116 :   gfc_add_modify (&se.pre, addr, label_tree);
     131              : 
     132          116 :   return gfc_finish_block (&se.pre);
     133              : }
     134              : 
     135              : /* Translate a GOTO statement.  */
     136              : 
     137              : tree
     138         1188 : gfc_trans_goto (gfc_code * code)
     139              : {
     140         1188 :   locus loc = code->loc;
     141         1188 :   tree assigned_goto;
     142         1188 :   tree target;
     143         1188 :   tree tmp;
     144         1188 :   gfc_se se;
     145              : 
     146         1188 :   if (code->label1 != NULL)
     147         1118 :     return build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
     148              : 
     149              :   /* ASSIGNED GOTO.  */
     150           70 :   gfc_init_se (&se, NULL);
     151           70 :   gfc_start_block (&se.pre);
     152           70 :   gfc_conv_label_variable (&se, code->expr1);
     153           70 :   tmp = GFC_DECL_STRING_LEN (se.expr);
     154           70 :   tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp,
     155           70 :                          build_int_cst (TREE_TYPE (tmp), -1));
     156           70 :   gfc_trans_runtime_check (true, false, tmp, &se.pre, &loc,
     157              :                            "Assigned label is not a target label");
     158              : 
     159           70 :   assigned_goto = GFC_DECL_ASSIGN_ADDR (se.expr);
     160              : 
     161              :   /* We're going to ignore a label list.  It does not really change the
     162              :      statement's semantics (because it is just a further restriction on
     163              :      what's legal code); before, we were comparing label addresses here, but
     164              :      that's a very fragile business and may break with optimization.  So
     165              :      just ignore it.  */
     166              : 
     167           70 :   target = fold_build1_loc (input_location, GOTO_EXPR, void_type_node,
     168              :                             assigned_goto);
     169           70 :   gfc_add_expr_to_block (&se.pre, target);
     170           70 :   return gfc_finish_block (&se.pre);
     171              : }
     172              : 
     173              : 
     174              : /* Translate an ENTRY statement.  Just adds a label for this entry point.  */
     175              : tree
     176         1341 : gfc_trans_entry (gfc_code * code)
     177              : {
     178         1341 :   return build1_v (LABEL_EXPR, code->ext.entry->label);
     179              : }
     180              : 
     181              : 
     182              : /* Replace a gfc_ss structure by another both in the gfc_se struct
     183              :    and the gfc_loopinfo struct.  This is used in gfc_conv_elemental_dependencies
     184              :    to replace a variable ss by the corresponding temporary.  */
     185              : 
     186              : static void
     187          343 : replace_ss (gfc_se *se, gfc_ss *old_ss, gfc_ss *new_ss)
     188              : {
     189          343 :   gfc_ss **sess, **loopss;
     190              : 
     191              :   /* The old_ss is a ss for a single variable.  */
     192          343 :   gcc_assert (old_ss->info->type == GFC_SS_SECTION);
     193              : 
     194          490 :   for (sess = &(se->ss); *sess != gfc_ss_terminator; sess = &((*sess)->next))
     195          490 :     if (*sess == old_ss)
     196              :       break;
     197          343 :   gcc_assert (*sess != gfc_ss_terminator);
     198              : 
     199          343 :   *sess = new_ss;
     200          343 :   new_ss->next = old_ss->next;
     201              : 
     202              :   /* Make sure that trailing references are not lost.  */
     203          343 :   if (old_ss->info
     204          343 :       && old_ss->info->data.array.ref
     205          343 :       && old_ss->info->data.array.ref->next
     206           25 :       && !(new_ss->info->data.array.ref
     207            0 :            && new_ss->info->data.array.ref->next))
     208           25 :     new_ss->info->data.array.ref = old_ss->info->data.array.ref;
     209              : 
     210          490 :   for (loopss = &(se->loop->ss); *loopss != gfc_ss_terminator;
     211          147 :        loopss = &((*loopss)->loop_chain))
     212          490 :     if (*loopss == old_ss)
     213              :       break;
     214          343 :   gcc_assert (*loopss != gfc_ss_terminator);
     215              : 
     216          343 :   *loopss = new_ss;
     217          343 :   new_ss->loop_chain = old_ss->loop_chain;
     218          343 :   new_ss->loop = old_ss->loop;
     219              : 
     220          343 :   gfc_free_ss (old_ss);
     221          343 : }
     222              : 
     223              : 
     224              : /* Check for dependencies between INTENT(IN) and INTENT(OUT) arguments of
     225              :    elemental subroutines.  Make temporaries for output arguments if any such
     226              :    dependencies are found.  Output arguments are chosen because internal_unpack
     227              :    can be used, as is, to copy the result back to the variable.  */
     228              : static void
     229         2234 : gfc_conv_elemental_dependencies (gfc_se * se, gfc_se * loopse,
     230              :                                  gfc_symbol * sym, gfc_actual_arglist * arg,
     231              :                                  gfc_dep_check check_variable)
     232              : {
     233         2234 :   gfc_actual_arglist *arg0;
     234         2234 :   gfc_expr *e;
     235         2234 :   gfc_formal_arglist *formal;
     236         2234 :   gfc_se parmse;
     237         2234 :   gfc_ss *ss;
     238         2234 :   gfc_symbol *fsym;
     239         2234 :   tree data;
     240         2234 :   tree size;
     241         2234 :   tree tmp;
     242              : 
     243         2234 :   if (loopse->ss == NULL)
     244            0 :     return;
     245              : 
     246         2234 :   ss = loopse->ss;
     247         2234 :   arg0 = arg;
     248         2234 :   formal = gfc_sym_get_dummy_args (sym);
     249              : 
     250              :   /* Loop over all the arguments testing for dependencies.  */
     251        11444 :   for (; arg != NULL; arg = arg->next, formal = formal ? formal->next : NULL)
     252              :     {
     253         4605 :       e = arg->expr;
     254         4605 :       if (e == NULL)
     255           12 :         continue;
     256              : 
     257              :       /* Obtain the info structure for the current argument.  */
     258         7945 :       for (ss = loopse->ss; ss && ss != gfc_ss_terminator; ss = ss->next)
     259         7679 :         if (ss->info->expr == e)
     260              :           break;
     261              : 
     262              :       /* If there is a dependency, create a temporary and use it
     263              :          instead of the variable.  */
     264         4593 :       fsym = formal ? formal->sym : NULL;
     265         4593 :       if (e->expr_type == EXPR_VARIABLE
     266         3418 :             && e->rank && fsym
     267         2909 :             && fsym->attr.intent != INTENT_IN
     268         1503 :             && !fsym->attr.value
     269         6036 :             && gfc_check_fncall_dependency (e, fsym->attr.intent,
     270              :                                             sym, arg0, check_variable))
     271              :         {
     272          343 :           tree initial, temptype;
     273          343 :           stmtblock_t temp_post;
     274          343 :           gfc_ss *tmp_ss;
     275              : 
     276          343 :           tmp_ss = gfc_get_array_ss (gfc_ss_terminator, NULL, ss->dimen,
     277              :                                      GFC_SS_SECTION);
     278          343 :           gfc_mark_ss_chain_used (tmp_ss, 1);
     279          343 :           tmp_ss->info->expr = ss->info->expr;
     280          343 :           replace_ss (loopse, ss, tmp_ss);
     281              : 
     282              :           /* Obtain the argument descriptor for unpacking.  */
     283          343 :           gfc_init_se (&parmse, NULL);
     284          343 :           parmse.want_pointer = 1;
     285          343 :           gfc_conv_expr_descriptor (&parmse, e);
     286          343 :           gfc_add_block_to_block (&se->pre, &parmse.pre);
     287              : 
     288              :           /* If we've got INTENT(INOUT) or a derived type with INTENT(OUT),
     289              :              initialize the array temporary with a copy of the values.  */
     290          343 :           if (fsym->attr.intent == INTENT_INOUT
     291          299 :                 || (fsym->ts.type ==BT_DERIVED
     292           51 :                       && fsym->attr.intent == INTENT_OUT))
     293           95 :             initial = parmse.expr;
     294              :           /* For class expressions, we always initialize with the copy of
     295              :              the values.  */
     296          248 :           else if (e->ts.type == BT_CLASS)
     297            6 :             initial = parmse.expr;
     298              :           else
     299              :             initial = NULL_TREE;
     300              : 
     301          343 :           if (e->ts.type != BT_CLASS)
     302              :             {
     303              :              /* Find the type of the temporary to create; we don't use the type
     304              :                 of e itself as this breaks for subcomponent-references in e
     305              :                 (where the type of e is that of the final reference, but
     306              :                 parmse.expr's type corresponds to the full derived-type).  */
     307              :              /* TODO: Fix this somehow so we don't need a temporary of the whole
     308              :                 array but instead only the components referenced.  */
     309          337 :               temptype = TREE_TYPE (parmse.expr); /* Pointer to descriptor.  */
     310          337 :               gcc_assert (TREE_CODE (temptype) == POINTER_TYPE);
     311          337 :               temptype = TREE_TYPE (temptype);
     312          337 :               temptype = gfc_get_element_type (temptype);
     313              :             }
     314              : 
     315              :           else
     316              :             /* For class arrays signal that the size of the dynamic type has to
     317              :                be obtained from the vtable, using the 'initial' expression.  */
     318              :             temptype = NULL_TREE;
     319              : 
     320              :           /* Generate the temporary.  Cleaning up the temporary should be the
     321              :              very last thing done, so we add the code to a new block and add it
     322              :              to se->post as last instructions.  */
     323          343 :           size = gfc_create_var (gfc_array_index_type, NULL);
     324          343 :           data = gfc_create_var (pvoid_type_node, NULL);
     325          343 :           gfc_init_block (&temp_post);
     326          686 :           tmp = gfc_trans_create_temp_array (&se->pre, &temp_post, tmp_ss,
     327              :                                              temptype, initial, false, true,
     328          343 :                                              false, &arg->expr->where);
     329          343 :           gfc_add_modify (&se->pre, size, tmp);
     330          343 :           tmp = fold_convert (pvoid_type_node, tmp_ss->info->data.array.data);
     331          343 :           gfc_add_modify (&se->pre, data, tmp);
     332              : 
     333              :           /* Update other ss' delta.  */
     334          343 :           gfc_set_delta (loopse->loop);
     335              : 
     336              :           /* Copy the result back using unpack.....  */
     337          343 :           if (e->ts.type != BT_CLASS)
     338          337 :             tmp = build_call_expr_loc (input_location,
     339              :                         gfor_fndecl_in_unpack, 2, parmse.expr, data);
     340              :           else
     341              :             {
     342              :               /* ... except for class results where the copy is
     343              :                  unconditional.  */
     344            6 :               tmp = build_fold_indirect_ref_loc (input_location, parmse.expr);
     345            6 :               tmp = gfc_conv_descriptor_data_get (tmp);
     346            6 :               tmp = build_call_expr_loc (input_location,
     347              :                                          builtin_decl_explicit (BUILT_IN_MEMCPY),
     348              :                                          3, tmp, data,
     349              :                                          fold_convert (size_type_node, size));
     350              :             }
     351          343 :           gfc_add_expr_to_block (&se->post, tmp);
     352              : 
     353              :           /* parmse.pre is already added above.  */
     354          343 :           gfc_add_block_to_block (&se->post, &parmse.post);
     355          343 :           gfc_add_block_to_block (&se->post, &temp_post);
     356              :         }
     357              :     }
     358              : }
     359              : 
     360              : 
     361              : /* Given an executable statement referring to an intrinsic function call,
     362              :    returns the intrinsic symbol.  */
     363              : 
     364              : static gfc_intrinsic_sym *
     365         6148 : get_intrinsic_for_code (gfc_code *code)
     366              : {
     367         6148 :   if (code->op == EXEC_CALL)
     368              :     {
     369         5805 :       gfc_intrinsic_sym * const isym = code->resolved_isym;
     370         5805 :       if (isym)
     371              :         return isym;
     372              :       else
     373         5608 :         return gfc_get_intrinsic_for_expr (code->expr1);
     374              :     }
     375              : 
     376              :   return NULL;
     377              : }
     378              : 
     379              : 
     380              : /* Handle the OpenACC routines acc_attach{,_async} and
     381              :    acc_detach{,_finalize}{,_async} explicitly.  This is required as the
     382              :    the corresponding device pointee is attached to the corresponding device
     383              :    pointer, but if a temporary array descriptor is created for the call,
     384              :    that one is used as pointer instead of the original pointer.  */
     385              : 
     386              : tree
     387           55 : gfc_trans_call_acc_attach_detach (gfc_code *code)
     388              : {
     389           55 :   stmtblock_t block;
     390           55 :   gfc_se ptr_addr_se, async_se;
     391           55 :   tree fn;
     392              : 
     393           55 :   fn = code->resolved_sym->backend_decl;
     394           55 :   if (fn == NULL)
     395              :     {
     396           18 :       fn = gfc_get_symbol_decl (code->resolved_sym);
     397           18 :       code->resolved_sym->backend_decl = fn;
     398              :     }
     399              : 
     400           55 :   gfc_start_block (&block);
     401              : 
     402           55 :   gfc_init_se (&ptr_addr_se, NULL);
     403           55 :   ptr_addr_se.descriptor_only = 1;
     404           55 :   ptr_addr_se.want_pointer = 1;
     405           55 :   gfc_conv_expr (&ptr_addr_se, code->ext.actual->expr);
     406           55 :   gfc_add_block_to_block (&block, &ptr_addr_se.pre);
     407           55 :   if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (ptr_addr_se.expr)))
     408           27 :     ptr_addr_se.expr = gfc_conv_descriptor_data_get (ptr_addr_se.expr);
     409           55 :   ptr_addr_se.expr = build_fold_addr_expr (ptr_addr_se.expr);
     410              : 
     411           55 :   bool async = code->ext.actual->next != NULL;
     412           55 :   if (async)
     413              :     {
     414            3 :       gfc_init_se (&async_se, NULL);
     415            3 :       gfc_conv_expr (&async_se, code->ext.actual->next->expr);
     416            3 :       fn = build_call_expr_loc (gfc_get_location (&code->loc), fn, 2,
     417              :                                 ptr_addr_se.expr, async_se.expr);
     418              :     }
     419              :   else
     420           52 :     fn = build_call_expr_loc (gfc_get_location (&code->loc),
     421              :                               fn, 1, ptr_addr_se.expr);
     422           55 :   gfc_add_expr_to_block (&block, fn);
     423           55 :   gfc_add_block_to_block (&block, &ptr_addr_se.post);
     424           55 :   if (async)
     425            3 :     gfc_add_block_to_block (&block, &async_se.post);
     426              : 
     427           55 :   return gfc_finish_block (&block);
     428              : }
     429              : 
     430              : 
     431              : /* Translate the CALL statement.  Builds a call to an F95 subroutine.  */
     432              : 
     433              : tree
     434        78213 : gfc_trans_call (gfc_code * code, bool dependency_check,
     435              :                 tree mask, tree count1, bool invert)
     436              : {
     437        78213 :   gfc_se se;
     438        78213 :   gfc_ss * ss;
     439        78213 :   int has_alternate_specifier;
     440        78213 :   gfc_dep_check check_variable;
     441        78213 :   tree index = NULL_TREE;
     442        78213 :   tree maskexpr = NULL_TREE;
     443        78213 :   tree tmp;
     444        78213 :   bool is_intrinsic_mvbits;
     445              : 
     446        78213 :   gcc_assert (code->resolved_sym);
     447              : 
     448              :   /* Unfortunately, acc_attach* and acc_detach* need some special treatment for
     449              :      attaching the the pointee to a pointer as GCC might introduce a temporary
     450              :      array descriptor, whose data component is then used as to be attached to
     451              :      pointer.  */
     452        78213 :   if (flag_openacc
     453         2455 :       && code->resolved_sym->attr.subroutine
     454         2449 :       && code->resolved_sym->formal
     455         1290 :       && code->resolved_sym->formal->sym->ts.type == BT_ASSUMED
     456          350 :       && code->resolved_sym->formal->sym->attr.dimension
     457          350 :       && code->resolved_sym->formal->sym->as->type == AS_ASSUMED_RANK
     458          243 :       && startswith (code->resolved_sym->name, "acc_")
     459        78456 :       && (!strcmp (code->resolved_sym->name + 4, "attach")
     460          217 :           || !strcmp (code->resolved_sym->name + 4, "attach_async")
     461          216 :           || !strcmp (code->resolved_sym->name + 4, "detach")
     462          191 :           || !strcmp (code->resolved_sym->name + 4, "detach_async")
     463          190 :           || !strcmp (code->resolved_sym->name + 4, "detach_finalize")
     464          189 :           || !strcmp (code->resolved_sym->name + 4, "detach_finalize_async")))
     465           55 :     return gfc_trans_call_acc_attach_detach (code);
     466              : 
     467              :   /* A CALL starts a new block because the actual arguments may have to
     468              :      be evaluated first.  */
     469        78158 :   gfc_init_se (&se, NULL);
     470        78158 :   gfc_start_block (&se.pre);
     471              : 
     472        78158 :   ss = gfc_ss_terminator;
     473        78158 :   if (code->resolved_sym->attr.elemental)
     474         6148 :     ss = gfc_walk_elemental_function_args (ss, code->ext.actual,
     475              :                                            get_intrinsic_for_code (code),
     476              :                                            GFC_SS_REFERENCE);
     477              : 
     478              :   /* MVBITS is inlined but needs the dependency checking found here.  */
     479       156316 :   is_intrinsic_mvbits = code->resolved_isym
     480        78158 :                         && code->resolved_isym->id == GFC_ISYM_MVBITS;
     481              : 
     482              :   /* Is not an elemental subroutine call with array valued arguments.  */
     483        78158 :   if (ss == gfc_ss_terminator)
     484              :     {
     485              : 
     486        75924 :       if (is_intrinsic_mvbits)
     487              :         {
     488          130 :           has_alternate_specifier = 0;
     489          130 :           gfc_conv_intrinsic_mvbits (&se, code->ext.actual, NULL);
     490              :         }
     491              :       else
     492              :         {
     493              :           /* Translate the call.  */
     494        75794 :           has_alternate_specifier =
     495        75794 :             gfc_conv_procedure_call (&se, code->resolved_sym,
     496              :                                      code->ext.actual, code->expr1, NULL);
     497              : 
     498              :           /* A subroutine without side-effect, by definition, does nothing!  */
     499        75794 :           TREE_SIDE_EFFECTS (se.expr) = 1;
     500              :         }
     501              : 
     502              :       /* Chain the pieces together and return the block.  */
     503        75924 :       if (has_alternate_specifier)
     504              :         {
     505          140 :           gfc_code *select_code;
     506          140 :           gfc_symbol *sym;
     507          140 :           select_code = code->next;
     508          140 :           gcc_assert(select_code->op == EXEC_SELECT);
     509          140 :           sym = select_code->expr1->symtree->n.sym;
     510          140 :           se.expr = convert (gfc_typenode_for_spec (&sym->ts), se.expr);
     511          140 :           if (sym->backend_decl == NULL)
     512            1 :             sym->backend_decl = gfc_get_symbol_decl (sym);
     513          140 :           gfc_add_modify (&se.pre, sym->backend_decl, se.expr);
     514              :         }
     515              :       else
     516        75784 :         gfc_add_expr_to_block (&se.pre, se.expr);
     517              : 
     518        75924 :       gfc_add_block_to_block (&se.finalblock, &se.post);
     519        75924 :       gfc_add_block_to_block (&se.pre, &se.finalblock);
     520              :     }
     521              : 
     522              :   else
     523              :     {
     524              :       /* An elemental subroutine call with array valued arguments has
     525              :          to be scalarized.  */
     526         2234 :       gfc_loopinfo loop;
     527         2234 :       stmtblock_t body;
     528         2234 :       stmtblock_t block;
     529         2234 :       gfc_se loopse;
     530         2234 :       gfc_se depse;
     531              : 
     532              :       /* gfc_walk_elemental_function_args renders the ss chain in the
     533              :          reverse order to the actual argument order.  */
     534         2234 :       ss = gfc_reverse_ss (ss);
     535              : 
     536              :       /* Initialize the loop.  */
     537         2234 :       gfc_init_se (&loopse, NULL);
     538         2234 :       gfc_init_loopinfo (&loop);
     539         2234 :       gfc_add_ss_to_loop (&loop, ss);
     540              : 
     541         2234 :       gfc_conv_ss_startstride (&loop);
     542              :       /* TODO: gfc_conv_loop_setup generates a temporary for vector
     543              :          subscripts.  This could be prevented in the elemental case
     544              :          as temporaries are handled separately
     545              :          (below in gfc_conv_elemental_dependencies).  */
     546         2234 :       if (code->expr1)
     547          237 :         gfc_conv_loop_setup (&loop, &code->expr1->where);
     548              :       else
     549         1997 :         gfc_conv_loop_setup (&loop, &code->loc);
     550              : 
     551         2234 :       gfc_mark_ss_chain_used (ss, 1);
     552              : 
     553              :       /* Convert the arguments, checking for dependencies.  */
     554         2234 :       gfc_copy_loopinfo_to_se (&loopse, &loop);
     555         2234 :       loopse.ss = ss;
     556              : 
     557              :       /* For operator assignment, do dependency checking.  */
     558         2234 :       if (dependency_check)
     559              :         check_variable = ELEM_CHECK_VARIABLE;
     560              :       else
     561         1910 :         check_variable = ELEM_DONT_CHECK_VARIABLE;
     562              : 
     563         2234 :       gfc_init_se (&depse, NULL);
     564         2234 :       gfc_conv_elemental_dependencies (&depse, &loopse, code->resolved_sym,
     565              :                                        code->ext.actual, check_variable);
     566              : 
     567         2234 :       gfc_add_block_to_block (&loop.pre,  &depse.pre);
     568         2234 :       gfc_add_block_to_block (&loop.post, &depse.post);
     569              : 
     570              :       /* Generate the loop body.  */
     571         2234 :       gfc_start_scalarized_body (&loop, &body);
     572         2234 :       gfc_init_block (&block);
     573              : 
     574         2234 :       if (mask && count1)
     575              :         {
     576              :           /* Form the mask expression according to the mask.  */
     577           44 :           index = count1;
     578           44 :           maskexpr = gfc_build_array_ref (mask, index, NULL);
     579           44 :           if (invert)
     580           11 :             maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
     581           11 :                                         TREE_TYPE (maskexpr), maskexpr);
     582              :         }
     583              : 
     584         2234 :       if (is_intrinsic_mvbits)
     585              :         {
     586           67 :           has_alternate_specifier = 0;
     587           67 :           gfc_conv_intrinsic_mvbits (&loopse, code->ext.actual, &loop);
     588              :         }
     589              :       else
     590              :         {
     591              :           /* Add the subroutine call to the block.  */
     592         2167 :           gfc_conv_procedure_call (&loopse, code->resolved_sym,
     593              :                                    code->ext.actual, code->expr1,
     594              :                                    NULL);
     595              :         }
     596              : 
     597         2234 :       if (mask && count1)
     598              :         {
     599           44 :           tmp = build3_v (COND_EXPR, maskexpr, loopse.expr,
     600              :                           build_empty_stmt (input_location));
     601           44 :           gfc_add_expr_to_block (&loopse.pre, tmp);
     602           44 :           tmp = fold_build2_loc (input_location, PLUS_EXPR,
     603              :                                  gfc_array_index_type,
     604              :                                  count1, gfc_index_one_node);
     605           44 :           gfc_add_modify (&loopse.pre, count1, tmp);
     606              :         }
     607              :       else
     608         2190 :         gfc_add_expr_to_block (&loopse.pre, loopse.expr);
     609              : 
     610         2234 :       gfc_add_block_to_block (&block, &loopse.pre);
     611         2234 :       gfc_add_block_to_block (&block, &loopse.post);
     612              : 
     613              :       /* Finish up the loop block and the loop.  */
     614         2234 :       gfc_add_expr_to_block (&body, gfc_finish_block (&block));
     615         2234 :       gfc_trans_scalarizing_loops (&loop, &body);
     616         2234 :       gfc_add_block_to_block (&se.pre, &loop.pre);
     617         2234 :       gfc_add_block_to_block (&se.pre, &loop.post);
     618         2234 :       gfc_add_block_to_block (&se.pre, &loopse.finalblock);
     619         2234 :       gfc_add_block_to_block (&se.pre, &se.post);
     620         2234 :       gfc_cleanup_loop (&loop);
     621              :     }
     622              : 
     623        78158 :   return gfc_finish_block (&se.pre);
     624              : }
     625              : 
     626              : 
     627              : /* Translate the RETURN statement.  */
     628              : 
     629              : tree
     630         3126 : gfc_trans_return (gfc_code * code)
     631              : {
     632         3126 :   if (code->expr1)
     633              :     {
     634           50 :       gfc_se se;
     635           50 :       tree tmp;
     636           50 :       tree result;
     637              : 
     638              :       /* If code->expr is not NULL, this return statement must appear
     639              :          in a subroutine and current_fake_result_decl has already
     640              :          been generated.  */
     641              : 
     642           50 :       result = gfc_get_fake_result_decl (NULL, 0);
     643           50 :       if (!result)
     644              :         {
     645            0 :           gfc_warning (0,
     646              :                        "An alternate return at %L without a * dummy argument",
     647            0 :                        &code->expr1->where);
     648            0 :           return gfc_generate_return ();
     649              :         }
     650              : 
     651              :       /* Start a new block for this statement.  */
     652           50 :       gfc_init_se (&se, NULL);
     653           50 :       gfc_start_block (&se.pre);
     654              : 
     655           50 :       gfc_conv_expr (&se, code->expr1);
     656              : 
     657              :       /* Note that the actually returned expression is a simple value and
     658              :          does not depend on any pointers or such; thus we can clean-up with
     659              :          se.post before returning.  */
     660           50 :       tmp = fold_build2_loc (input_location, MODIFY_EXPR, TREE_TYPE (result),
     661           50 :                              result, fold_convert (TREE_TYPE (result),
     662              :                              se.expr));
     663           50 :       gfc_add_expr_to_block (&se.pre, tmp);
     664           50 :       gfc_add_block_to_block (&se.pre, &se.post);
     665              : 
     666           50 :       tmp = gfc_generate_return ();
     667           50 :       gfc_add_expr_to_block (&se.pre, tmp);
     668           50 :       return gfc_finish_block (&se.pre);
     669              :     }
     670              : 
     671         3076 :   return gfc_generate_return ();
     672              : }
     673              : 
     674              : 
     675              : /* Translate the PAUSE statement.  We have to translate this statement
     676              :    to a runtime library call.  */
     677              : 
     678              : tree
     679           28 : gfc_trans_pause (gfc_code * code)
     680              : {
     681           28 :   tree gfc_int8_type_node = gfc_get_int_type (8);
     682           28 :   gfc_se se;
     683           28 :   tree tmp;
     684              : 
     685              :   /* Start a new block for this statement.  */
     686           28 :   gfc_init_se (&se, NULL);
     687           28 :   gfc_start_block (&se.pre);
     688              : 
     689              : 
     690           28 :   if (code->expr1 == NULL)
     691              :     {
     692           10 :       tmp = build_int_cst (size_type_node, 0);
     693           10 :       tmp = build_call_expr_loc (input_location,
     694              :                                  gfor_fndecl_pause_string, 2,
     695              :                                  build_int_cst (pchar_type_node, 0), tmp);
     696              :     }
     697           18 :   else if (code->expr1->ts.type == BT_INTEGER)
     698              :     {
     699            9 :       gfc_conv_expr (&se, code->expr1);
     700            9 :       tmp = build_call_expr_loc (input_location,
     701              :                                  gfor_fndecl_pause_numeric, 1,
     702              :                                  fold_convert (gfc_int8_type_node, se.expr));
     703              :     }
     704              :   else
     705              :     {
     706            9 :       gfc_conv_expr_reference (&se, code->expr1);
     707            9 :       tmp = build_call_expr_loc (input_location,
     708              :                              gfor_fndecl_pause_string, 2,
     709              :                                  se.expr, fold_convert (size_type_node,
     710              :                                                         se.string_length));
     711              :     }
     712              : 
     713           28 :   gfc_add_expr_to_block (&se.pre, tmp);
     714              : 
     715           28 :   gfc_add_block_to_block (&se.pre, &se.post);
     716              : 
     717           28 :   return gfc_finish_block (&se.pre);
     718              : }
     719              : 
     720              : 
     721              : /* Translate the STOP statement.  We have to translate this statement
     722              :    to a runtime library call.  */
     723              : 
     724              : tree
     725       215641 : gfc_trans_stop (gfc_code *code, bool error_stop)
     726              : {
     727       215641 :   gfc_se se;
     728       215641 :   tree tmp;
     729       215641 :   tree quiet;
     730              : 
     731              :   /* Start a new block for this statement.  */
     732       215641 :   gfc_init_se (&se, NULL);
     733       215641 :   gfc_start_block (&se.pre);
     734              : 
     735       215641 :   if (code->expr2)
     736              :     {
     737           25 :       gfc_conv_expr_val (&se, code->expr2);
     738           25 :       quiet = fold_convert (boolean_type_node, se.expr);
     739              :     }
     740              :   else
     741       215616 :     quiet = boolean_false_node;
     742              : 
     743       215641 :   if (code->expr1 == NULL)
     744              :     {
     745        20421 :       tmp = build_int_cst (size_type_node, 0);
     746        40842 :       tmp = build_call_expr_loc (input_location,
     747              :                                  error_stop
     748        19460 :                                  ? (flag_coarray == GFC_FCOARRAY_LIB
     749        19460 :                                     ? gfor_fndecl_caf_error_stop_str
     750              :                                     : gfor_fndecl_error_stop_string)
     751          961 :                                  : (flag_coarray == GFC_FCOARRAY_LIB
     752          961 :                                     ? gfor_fndecl_caf_stop_str
     753              :                                     : gfor_fndecl_stop_string),
     754              :                                  3, build_int_cst (pchar_type_node, 0), tmp,
     755              :                                  quiet);
     756              :     }
     757       195220 :   else if (code->expr1->ts.type == BT_INTEGER)
     758              :     {
     759       194779 :       gfc_conv_expr (&se, code->expr1);
     760       389558 :       tmp = build_call_expr_loc (input_location,
     761              :                                  error_stop
     762        19289 :                                  ? (flag_coarray == GFC_FCOARRAY_LIB
     763        19289 :                                     ? gfor_fndecl_caf_error_stop
     764              :                                     : gfor_fndecl_error_stop_numeric)
     765       175490 :                                  : (flag_coarray == GFC_FCOARRAY_LIB
     766       175490 :                                     ? gfor_fndecl_caf_stop_numeric
     767              :                                     : gfor_fndecl_stop_numeric), 2,
     768              :                                  fold_convert (integer_type_node, se.expr),
     769              :                                  quiet);
     770              :     }
     771              :   else
     772              :     {
     773          441 :       gfc_conv_expr_reference (&se, code->expr1);
     774          882 :       tmp = build_call_expr_loc (input_location,
     775              :                                  error_stop
     776          331 :                                  ? (flag_coarray == GFC_FCOARRAY_LIB
     777          331 :                                     ? gfor_fndecl_caf_error_stop_str
     778              :                                     : gfor_fndecl_error_stop_string)
     779          110 :                                  : (flag_coarray == GFC_FCOARRAY_LIB
     780          110 :                                     ? gfor_fndecl_caf_stop_str
     781              :                                     : gfor_fndecl_stop_string),
     782              :                                  3, se.expr, fold_convert (size_type_node,
     783              :                                                            se.string_length),
     784              :                                  quiet);
     785              :     }
     786              : 
     787       215641 :   gfc_add_expr_to_block (&se.pre, tmp);
     788              : 
     789       215641 :   gfc_add_block_to_block (&se.pre, &se.post);
     790              : 
     791       215641 :   return gfc_finish_block (&se.pre);
     792              : }
     793              : 
     794              : tree
     795           60 : trans_exit ()
     796              : {
     797           60 :   const char *name = gfc_get_string (PREFIX ("exit_i%d"), 4);
     798           60 :   gfc_symbol *exsym = gfc_get_intrinsic_sub_symbol (name);
     799           60 :   tree tmp = gfc_get_symbol_decl (exsym);
     800           60 :   return build_call_expr_loc (input_location, tmp, 1, integer_zero_node);
     801              : }
     802              : 
     803              : /* Translate the FAIL IMAGE statement.  */
     804              : 
     805              : tree
     806           10 : gfc_trans_fail_image (gfc_code *code ATTRIBUTE_UNUSED)
     807              : {
     808           10 :   if (flag_coarray == GFC_FCOARRAY_LIB)
     809            7 :     return build_call_expr_loc (input_location,
     810            7 :                                 gfor_fndecl_caf_fail_image, 0);
     811              :   else
     812            3 :     return trans_exit ();
     813              : }
     814              : 
     815              : void
     816          470 : gfc_trans_sync_stat (struct sync_stat *sync_stat, gfc_se *se, tree *stat,
     817              :                      tree *errmsg, tree *errmsg_len)
     818              : {
     819          470 :   gfc_se argse;
     820              : 
     821          470 :   if (sync_stat->stat)
     822              :     {
     823           72 :       gfc_init_se (&argse, NULL);
     824           72 :       gfc_conv_expr (&argse, sync_stat->stat);
     825           72 :       gfc_add_block_to_block (&se->pre, &argse.pre);
     826              : 
     827           72 :       if (TREE_TYPE (argse.expr) != integer_type_node)
     828              :         {
     829            6 :           tree tstat = gfc_create_var (integer_type_node, "stat");
     830            6 :           TREE_THIS_VOLATILE (tstat) = 1;
     831            6 :           gfc_add_modify (&se->pre, tstat,
     832              :                           fold_convert (integer_type_node, argse.expr));
     833            6 :           gfc_add_modify (&se->post, argse.expr,
     834            6 :                           fold_convert (TREE_TYPE (argse.expr), tstat));
     835            6 :           *stat = build_fold_addr_expr (tstat);
     836              :         }
     837              :       else
     838           66 :         *stat = build_fold_addr_expr (argse.expr);
     839              :     }
     840              :   else
     841          398 :     *stat = null_pointer_node;
     842              : 
     843          470 :   if (sync_stat->errmsg)
     844              :     {
     845           42 :       gfc_init_se (&argse, NULL);
     846           42 :       gfc_conv_expr_reference (&argse, sync_stat->errmsg);
     847           42 :       gfc_add_block_to_block (&se->pre, &argse.pre);
     848           42 :       *errmsg = argse.expr;
     849           42 :       *errmsg_len = fold_convert (size_type_node, argse.string_length);
     850              :     }
     851              :   else
     852              :     {
     853          428 :       *errmsg = null_pointer_node;
     854          428 :       *errmsg_len = build_zero_cst (size_type_node);
     855              :     }
     856          470 : }
     857              : 
     858              : /* Translate the FORM TEAM statement.  */
     859              : 
     860              : tree
     861          117 : gfc_trans_form_team (gfc_code *code)
     862              : {
     863          117 :   if (flag_coarray == GFC_FCOARRAY_LIB)
     864              :     {
     865           80 :       gfc_se se, argse;
     866           80 :       tree team_id, team_type, new_index, stat, errmsg, errmsg_len, tmp;
     867              : 
     868           80 :       gfc_init_se (&se, NULL);
     869           80 :       gfc_init_se (&argse, NULL);
     870              : 
     871           80 :       gfc_conv_expr_val (&argse, code->expr1);
     872           80 :       team_id = fold_convert (integer_type_node, argse.expr);
     873           80 :       gfc_conv_expr_reference (&argse, code->expr2);
     874           80 :       team_type = argse.expr;
     875              : 
     876              :       /* NEW_INDEX=.  */
     877           80 :       if (code->expr3)
     878              :         {
     879           24 :           gfc_conv_expr_reference (&argse, code->expr3);
     880           24 :           new_index = argse.expr;
     881              :         }
     882              :       else
     883           56 :         new_index = null_pointer_node;
     884              : 
     885           80 :       gfc_add_block_to_block (&se.post, &argse.post);
     886              : 
     887           80 :       gfc_trans_sync_stat (&code->ext.sync_stat, &se, &stat, &errmsg,
     888              :                            &errmsg_len);
     889              : 
     890           80 :       gfc_add_block_to_block (&se.pre, &argse.pre);
     891              : 
     892           80 :       tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_form_team, 6,
     893              :                                  team_id, team_type, new_index, stat, errmsg,
     894              :                                  errmsg_len);
     895           80 :       gfc_add_expr_to_block (&se.pre, tmp);
     896           80 :       gfc_add_block_to_block (&se.pre, &se.post);
     897           80 :       return gfc_finish_block (&se.pre);
     898              :      }
     899              :   else
     900           37 :     return trans_exit ();
     901              : }
     902              : 
     903              : /* Translate the CHANGE TEAM statement.  */
     904              : 
     905              : tree
     906           57 : gfc_trans_change_team (gfc_code *code)
     907              : {
     908           57 :   if (flag_coarray == GFC_FCOARRAY_LIB)
     909              :     {
     910           37 :       stmtblock_t block;
     911           37 :       gfc_se se;
     912           37 :       tree team_type, stat, errmsg, errmsg_len, tmp;
     913              : 
     914           37 :       gfc_init_se (&se, NULL);
     915           37 :       gfc_start_block (&block);
     916              : 
     917           37 :       gfc_conv_expr_val (&se, code->expr1);
     918           37 :       team_type = se.expr;
     919              : 
     920           37 :       gfc_trans_sync_stat (&code->ext.block.sync_stat, &se, &stat, &errmsg,
     921              :                            &errmsg_len);
     922              : 
     923           37 :       tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_change_team, 4,
     924              :                                  team_type, stat, errmsg, errmsg_len);
     925              : 
     926           37 :       gfc_add_expr_to_block (&se.pre, tmp);
     927           37 :       gfc_add_block_to_block (&se.pre, &se.post);
     928           37 :       gfc_add_block_to_block (&block, &se.pre);
     929           37 :       gfc_add_expr_to_block (&block, gfc_trans_block_construct (code));
     930           37 :       return gfc_finish_block (&block);
     931              :     }
     932              :   else
     933           20 :     return trans_exit ();
     934              : }
     935              : 
     936              : /* Translate the END TEAM statement.  */
     937              : 
     938              : tree
     939           37 : gfc_trans_end_team (gfc_code *code)
     940              : {
     941           37 :   if (flag_coarray == GFC_FCOARRAY_LIB)
     942              :     {
     943           37 :       gfc_se se;
     944           37 :       tree stat, errmsg, errmsg_len, tmp;
     945              : 
     946           37 :       gfc_init_se (&se, NULL);
     947           37 :       gfc_start_block (&se.pre);
     948              : 
     949           37 :       gfc_trans_sync_stat (&code->ext.sync_stat, &se, &stat, &errmsg,
     950              :                            &errmsg_len);
     951              : 
     952           37 :       tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_end_team, 3,
     953              :                                  stat, errmsg, errmsg_len);
     954           37 :       gfc_add_expr_to_block (&se.pre, tmp);
     955           37 :       gfc_add_block_to_block (&se.pre, &se.post);
     956           37 :       return gfc_finish_block (&se.pre);
     957              :     }
     958              :   else
     959            0 :     return trans_exit ();
     960              : }
     961              : 
     962              : /* Translate the SYNC TEAM statement.  */
     963              : 
     964              : tree
     965           32 : gfc_trans_sync_team (gfc_code *code)
     966              : {
     967           32 :   if (flag_coarray == GFC_FCOARRAY_LIB)
     968              :     {
     969           32 :       gfc_se se;
     970           32 :       tree team_type, stat, errmsg, errmsg_len, tmp;
     971              : 
     972           32 :       gfc_init_se (&se, NULL);
     973              : 
     974           32 :       gfc_conv_expr_val (&se, code->expr1);
     975           32 :       team_type = se.expr;
     976              : 
     977           32 :       gfc_trans_sync_stat (&code->ext.sync_stat, &se, &stat, &errmsg,
     978              :                            &errmsg_len);
     979              : 
     980           32 :       tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_team, 4,
     981              :                                  team_type, stat, errmsg, errmsg_len);
     982           32 :       gfc_add_expr_to_block (&se.pre, tmp);
     983           32 :       gfc_add_block_to_block (&se.pre, &se.post);
     984           32 :       return gfc_finish_block (&se.pre);
     985              :     }
     986              :   else
     987            0 :     return trans_exit ();
     988              : }
     989              : 
     990              : tree
     991          126 : gfc_trans_lock_unlock (gfc_code *code, gfc_exec_op op)
     992              : {
     993          126 :   gfc_se se, argse;
     994          126 :   tree stat = NULL_TREE, stat2 = NULL_TREE;
     995          126 :   tree lock_acquired = NULL_TREE, lock_acquired2 = NULL_TREE;
     996              : 
     997              :   /* Short cut: For single images without STAT= or LOCK_ACQUIRED
     998              :      return early. (ERRMSG= is always untouched for -fcoarray=single.)  */
     999          126 :   if (!code->expr2 && !code->expr4 && flag_coarray != GFC_FCOARRAY_LIB)
    1000              :     return NULL_TREE;
    1001              : 
    1002          106 :   if (code->expr2)
    1003              :     {
    1004           40 :       gcc_assert (code->expr2->expr_type == EXPR_VARIABLE);
    1005           40 :       gfc_init_se (&argse, NULL);
    1006           40 :       gfc_conv_expr_val (&argse, code->expr2);
    1007           40 :       stat = argse.expr;
    1008              :     }
    1009           66 :   else if (flag_coarray == GFC_FCOARRAY_LIB)
    1010           60 :     stat = null_pointer_node;
    1011              : 
    1012          106 :   if (code->expr4)
    1013              :     {
    1014           20 :       gcc_assert (code->expr4->expr_type == EXPR_VARIABLE);
    1015           20 :       gfc_init_se (&argse, NULL);
    1016           20 :       gfc_conv_expr_val (&argse, code->expr4);
    1017           20 :       lock_acquired = argse.expr;
    1018              :     }
    1019           86 :   else if (flag_coarray == GFC_FCOARRAY_LIB)
    1020           74 :     lock_acquired = null_pointer_node;
    1021              : 
    1022          106 :   gfc_start_block (&se.pre);
    1023          106 :   if (flag_coarray == GFC_FCOARRAY_LIB)
    1024              :     {
    1025           88 :       tree tmp, token, image_index, errmsg, errmsg_len;
    1026           88 :       tree index = build_zero_cst (gfc_array_index_type);
    1027           88 :       tree caf_decl = gfc_get_tree_for_caf_expr (code->expr1);
    1028              : 
    1029           88 :       if (code->expr1->symtree->n.sym->ts.type != BT_DERIVED
    1030           88 :           || code->expr1->symtree->n.sym->ts.u.derived->from_intmod
    1031              :              != INTMOD_ISO_FORTRAN_ENV
    1032           84 :           || code->expr1->symtree->n.sym->ts.u.derived->intmod_sym_id
    1033              :              != ISOFORTRAN_LOCK_TYPE)
    1034              :         {
    1035            4 :           gfc_error ("Sorry, the lock component of derived type at %L is not "
    1036              :                      "yet supported", &code->expr1->where);
    1037            4 :           return NULL_TREE;
    1038              :         }
    1039              : 
    1040           84 :       gfc_get_caf_token_offset (&se, &token, NULL, caf_decl, NULL_TREE,
    1041              :                                 code->expr1);
    1042              : 
    1043           84 :       if (gfc_is_coindexed (code->expr1))
    1044           30 :         image_index = gfc_caf_get_image_index (&se.pre, code->expr1, caf_decl);
    1045              :       else
    1046           54 :         image_index = integer_zero_node;
    1047              : 
    1048              :       /* For arrays, obtain the array index.  */
    1049           84 :       if (gfc_expr_attr (code->expr1).dimension)
    1050              :         {
    1051           52 :           tree desc, tmp, extent, lbound, ubound;
    1052           52 :           gfc_array_ref *ar, ar2;
    1053           52 :           int i, rank;
    1054              : 
    1055              :           /* TODO: Extend this, once DT components are supported.  */
    1056           52 :           ar = &code->expr1->ref->u.ar;
    1057           52 :           ar2 = *ar;
    1058           52 :           memset (ar, '\0', sizeof (*ar));
    1059           52 :           ar->as = ar2.as;
    1060           52 :           ar->type = AR_FULL;
    1061           52 :           rank = code->expr1->rank;
    1062           52 :           code->expr1->rank = ar->as->rank;
    1063              : 
    1064           52 :           gfc_init_se (&argse, NULL);
    1065           52 :           argse.descriptor_only = 1;
    1066           52 :           gfc_conv_expr_descriptor (&argse, code->expr1);
    1067           52 :           gfc_add_block_to_block (&se.pre, &argse.pre);
    1068           52 :           desc = argse.expr;
    1069           52 :           *ar = ar2;
    1070           52 :           code->expr1->rank = rank;
    1071              : 
    1072           52 :           extent = build_one_cst (gfc_array_index_type);
    1073          182 :           for (i = 0; i < ar->dimen; i++)
    1074              :             {
    1075           78 :               gfc_init_se (&argse, NULL);
    1076           78 :               gfc_conv_expr_type (&argse, ar->start[i], gfc_array_index_type);
    1077           78 :               gfc_add_block_to_block (&argse.pre, &argse.pre);
    1078           78 :               lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
    1079           78 :               tmp = fold_build2_loc (input_location, MINUS_EXPR,
    1080           78 :                                      TREE_TYPE (lbound), argse.expr, lbound);
    1081           78 :               tmp = fold_build2_loc (input_location, MULT_EXPR,
    1082           78 :                                      TREE_TYPE (tmp), extent, tmp);
    1083           78 :               index = fold_build2_loc (input_location, PLUS_EXPR,
    1084           78 :                                        TREE_TYPE (tmp), index, tmp);
    1085           78 :               if (i < ar->dimen - 1)
    1086              :                 {
    1087           26 :                   ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
    1088           26 :                   tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL);
    1089           26 :                   extent = fold_build2_loc (input_location, MULT_EXPR,
    1090           26 :                                             TREE_TYPE (tmp), extent, tmp);
    1091              :                 }
    1092              :             }
    1093              :         }
    1094              : 
    1095              :       /* errmsg.  */
    1096           84 :       if (code->expr3)
    1097              :         {
    1098            0 :           gfc_init_se (&argse, NULL);
    1099            0 :           argse.want_pointer = 1;
    1100            0 :           gfc_conv_expr (&argse, code->expr3);
    1101            0 :           gfc_add_block_to_block (&se.pre, &argse.pre);
    1102            0 :           errmsg = argse.expr;
    1103            0 :           errmsg_len = fold_convert (size_type_node, argse.string_length);
    1104              :         }
    1105              :       else
    1106              :         {
    1107           84 :           errmsg = null_pointer_node;
    1108           84 :           errmsg_len = build_zero_cst (size_type_node);
    1109              :         }
    1110              : 
    1111           84 :       if (stat != null_pointer_node && TREE_TYPE (stat) != integer_type_node)
    1112              :         {
    1113            0 :           stat2 = stat;
    1114            0 :           stat = gfc_create_var (integer_type_node, "stat");
    1115              :         }
    1116              : 
    1117           84 :       if (lock_acquired != null_pointer_node
    1118           84 :           && TREE_TYPE (lock_acquired) != integer_type_node)
    1119              :         {
    1120           14 :           lock_acquired2 = lock_acquired;
    1121           14 :           lock_acquired = gfc_create_var (integer_type_node, "acquired");
    1122              :         }
    1123              : 
    1124           84 :       index = fold_convert (size_type_node, index);
    1125           84 :       if (op == EXEC_LOCK)
    1126           42 :         tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_lock, 7,
    1127              :                                    token, index, image_index,
    1128           42 :                                    lock_acquired != null_pointer_node
    1129           14 :                                    ? gfc_build_addr_expr (NULL, lock_acquired)
    1130              :                                    : lock_acquired,
    1131           42 :                                    stat != null_pointer_node
    1132           14 :                                    ? gfc_build_addr_expr (NULL, stat) : stat,
    1133              :                                    errmsg, errmsg_len);
    1134              :       else
    1135           42 :         tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_unlock, 6,
    1136              :                                    token, index, image_index,
    1137           42 :                                    stat != null_pointer_node
    1138           14 :                                    ? gfc_build_addr_expr (NULL, stat) : stat,
    1139              :                                    errmsg, errmsg_len);
    1140           84 :       gfc_add_expr_to_block (&se.pre, tmp);
    1141              : 
    1142              :       /* It guarantees memory consistency within the same segment */
    1143           84 :       tmp = gfc_build_string_const (strlen ("memory")+1, "memory"),
    1144           84 :       tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
    1145              :                         gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
    1146              :                         tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
    1147           84 :       ASM_VOLATILE_P (tmp) = 1;
    1148              : 
    1149           84 :       gfc_add_expr_to_block (&se.pre, tmp);
    1150              : 
    1151           84 :       if (stat2 != NULL_TREE)
    1152            0 :         gfc_add_modify (&se.pre, stat2,
    1153            0 :                         fold_convert (TREE_TYPE (stat2), stat));
    1154              : 
    1155           84 :       if (lock_acquired2 != NULL_TREE)
    1156           14 :         gfc_add_modify (&se.pre, lock_acquired2,
    1157           14 :                         fold_convert (TREE_TYPE (lock_acquired2),
    1158              :                                       lock_acquired));
    1159              : 
    1160           84 :       return gfc_finish_block (&se.pre);
    1161              :     }
    1162              : 
    1163           18 :   if (stat != NULL_TREE)
    1164           12 :     gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
    1165              : 
    1166           18 :   if (lock_acquired != NULL_TREE)
    1167            6 :     gfc_add_modify (&se.pre, lock_acquired,
    1168            6 :                     fold_convert (TREE_TYPE (lock_acquired),
    1169              :                                   boolean_true_node));
    1170              : 
    1171           18 :   return gfc_finish_block (&se.pre);
    1172              : }
    1173              : 
    1174              : tree
    1175           58 : gfc_trans_event_post_wait (gfc_code *code, gfc_exec_op op)
    1176              : {
    1177           58 :   gfc_se se, argse;
    1178           58 :   tree stat = NULL_TREE, stat2 = NULL_TREE;
    1179           58 :   tree until_count = NULL_TREE;
    1180              : 
    1181           58 :   if (code->expr2)
    1182              :     {
    1183           12 :       gcc_assert (code->expr2->expr_type == EXPR_VARIABLE);
    1184           12 :       gfc_init_se (&argse, NULL);
    1185           12 :       gfc_conv_expr_val (&argse, code->expr2);
    1186           12 :       stat = argse.expr;
    1187              :     }
    1188           46 :   else if (flag_coarray == GFC_FCOARRAY_LIB)
    1189           31 :     stat = null_pointer_node;
    1190              : 
    1191           58 :   if (code->expr4)
    1192              :     {
    1193           18 :       gfc_init_se (&argse, NULL);
    1194           18 :       gfc_conv_expr_val (&argse, code->expr4);
    1195           18 :       until_count = fold_convert (integer_type_node, argse.expr);
    1196              :     }
    1197              :   else
    1198           40 :     until_count = integer_one_node;
    1199              : 
    1200           58 :   if (flag_coarray != GFC_FCOARRAY_LIB)
    1201              :     {
    1202           19 :       gfc_start_block (&se.pre);
    1203           19 :       gfc_init_se (&argse, NULL);
    1204           19 :       gfc_conv_expr_val (&argse, code->expr1);
    1205              : 
    1206           19 :       if (op == EXEC_EVENT_POST)
    1207           22 :         gfc_add_modify (&se.pre, argse.expr,
    1208              :                         fold_build2_loc (input_location, PLUS_EXPR,
    1209           11 :                                 TREE_TYPE (argse.expr), argse.expr,
    1210           11 :                                 build_int_cst (TREE_TYPE (argse.expr), 1)));
    1211              :       else
    1212           16 :         gfc_add_modify (&se.pre, argse.expr,
    1213              :                         fold_build2_loc (input_location, MINUS_EXPR,
    1214            8 :                                 TREE_TYPE (argse.expr), argse.expr,
    1215            8 :                                 fold_convert (TREE_TYPE (argse.expr),
    1216              :                                               until_count)));
    1217           19 :       if (stat != NULL_TREE)
    1218            4 :         gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
    1219              : 
    1220           19 :       return gfc_finish_block (&se.pre);
    1221              :     }
    1222              : 
    1223           39 :   gfc_start_block (&se.pre);
    1224           39 :   tree tmp, token, image_index, errmsg, errmsg_len;
    1225           39 :   tree index = build_zero_cst (gfc_array_index_type);
    1226           39 :   tree caf_decl = gfc_get_tree_for_caf_expr (code->expr1);
    1227              : 
    1228           39 :   if (code->expr1->symtree->n.sym->ts.type != BT_DERIVED
    1229           39 :       || code->expr1->symtree->n.sym->ts.u.derived->from_intmod
    1230              :          != INTMOD_ISO_FORTRAN_ENV
    1231           39 :       || code->expr1->symtree->n.sym->ts.u.derived->intmod_sym_id
    1232              :          != ISOFORTRAN_EVENT_TYPE)
    1233              :     {
    1234            0 :       gfc_error ("Sorry, the event component of derived type at %L is not "
    1235              :                  "yet supported", &code->expr1->where);
    1236            0 :       return NULL_TREE;
    1237              :     }
    1238              : 
    1239           39 :   gfc_init_se (&argse, NULL);
    1240           39 :   gfc_get_caf_token_offset (&argse, &token, NULL, caf_decl, NULL_TREE,
    1241              :                             code->expr1);
    1242           39 :   gfc_add_block_to_block (&se.pre, &argse.pre);
    1243              : 
    1244           39 :   if (gfc_is_coindexed (code->expr1))
    1245           11 :     image_index = gfc_caf_get_image_index (&se.pre, code->expr1, caf_decl);
    1246              :   else
    1247           28 :     image_index = integer_zero_node;
    1248              : 
    1249              :   /* For arrays, obtain the array index.  */
    1250           39 :   if (gfc_expr_attr (code->expr1).dimension)
    1251              :     {
    1252           14 :       tree desc, tmp, extent, lbound, ubound;
    1253           14 :       gfc_array_ref *ar, ar2;
    1254           14 :       int i;
    1255              : 
    1256              :       /* TODO: Extend this, once DT components are supported.  */
    1257           14 :       ar = &code->expr1->ref->u.ar;
    1258           14 :       ar2 = *ar;
    1259           14 :       memset (ar, '\0', sizeof (*ar));
    1260           14 :       ar->as = ar2.as;
    1261           14 :       ar->type = AR_FULL;
    1262              : 
    1263           14 :       gfc_init_se (&argse, NULL);
    1264           14 :       argse.descriptor_only = 1;
    1265           14 :       gfc_conv_expr_descriptor (&argse, code->expr1);
    1266           14 :       gfc_add_block_to_block (&se.pre, &argse.pre);
    1267           14 :       desc = argse.expr;
    1268           14 :       *ar = ar2;
    1269              : 
    1270           14 :       extent = build_one_cst (gfc_array_index_type);
    1271           42 :       for (i = 0; i < ar->dimen; i++)
    1272              :         {
    1273           14 :           gfc_init_se (&argse, NULL);
    1274           14 :           gfc_conv_expr_type (&argse, ar->start[i], gfc_array_index_type);
    1275           14 :           gfc_add_block_to_block (&argse.pre, &argse.pre);
    1276           14 :           lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
    1277           14 :           tmp = fold_build2_loc (input_location, MINUS_EXPR,
    1278           14 :                                  TREE_TYPE (lbound), argse.expr, lbound);
    1279           14 :           tmp = fold_build2_loc (input_location, MULT_EXPR,
    1280           14 :                                  TREE_TYPE (tmp), extent, tmp);
    1281           14 :           index = fold_build2_loc (input_location, PLUS_EXPR,
    1282           14 :                                    TREE_TYPE (tmp), index, tmp);
    1283           14 :           if (i < ar->dimen - 1)
    1284              :             {
    1285            0 :               ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
    1286            0 :               tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL);
    1287            0 :               extent = fold_build2_loc (input_location, MULT_EXPR,
    1288            0 :                                         TREE_TYPE (tmp), extent, tmp);
    1289              :             }
    1290              :         }
    1291              :     }
    1292              : 
    1293              :   /* errmsg.  */
    1294           39 :   if (code->expr3)
    1295              :     {
    1296            0 :       gfc_init_se (&argse, NULL);
    1297            0 :       argse.want_pointer = 1;
    1298            0 :       gfc_conv_expr (&argse, code->expr3);
    1299            0 :       gfc_add_block_to_block (&se.pre, &argse.pre);
    1300            0 :       errmsg = argse.expr;
    1301            0 :       errmsg_len = fold_convert (size_type_node, argse.string_length);
    1302              :     }
    1303              :   else
    1304              :     {
    1305           39 :       errmsg = null_pointer_node;
    1306           39 :       errmsg_len = build_zero_cst (size_type_node);
    1307              :     }
    1308              : 
    1309           39 :   if (stat != null_pointer_node && TREE_TYPE (stat) != integer_type_node)
    1310              :     {
    1311            0 :       stat2 = stat;
    1312            0 :       stat = gfc_create_var (integer_type_node, "stat");
    1313              :     }
    1314              : 
    1315           39 :   index = fold_convert (size_type_node, index);
    1316           39 :   if (op == EXEC_EVENT_POST)
    1317           23 :     tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_event_post, 6,
    1318              :                                token, index, image_index,
    1319           23 :                                stat != null_pointer_node
    1320            4 :                                ? gfc_build_addr_expr (NULL, stat) : stat,
    1321              :                                errmsg, errmsg_len);
    1322              :   else
    1323           16 :     tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_event_wait, 6,
    1324              :                                token, index, until_count,
    1325           16 :                                stat != null_pointer_node
    1326            4 :                                ? gfc_build_addr_expr (NULL, stat) : stat,
    1327              :                                errmsg, errmsg_len);
    1328           39 :   gfc_add_expr_to_block (&se.pre, tmp);
    1329              : 
    1330              :   /* It guarantees memory consistency within the same segment */
    1331           39 :   tmp = gfc_build_string_const (strlen ("memory")+1, "memory"),
    1332           39 :   tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
    1333              :                     gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
    1334              :                     tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
    1335           39 :   ASM_VOLATILE_P (tmp) = 1;
    1336           39 :   gfc_add_expr_to_block (&se.pre, tmp);
    1337              : 
    1338           39 :   if (stat2 != NULL_TREE)
    1339            0 :     gfc_add_modify (&se.pre, stat2, fold_convert (TREE_TYPE (stat2), stat));
    1340              : 
    1341           39 :   return gfc_finish_block (&se.pre);
    1342              : }
    1343              : 
    1344              : tree
    1345         1277 : gfc_trans_sync (gfc_code *code, gfc_exec_op type)
    1346              : {
    1347         1277 :   gfc_se se, argse;
    1348         1277 :   tree tmp;
    1349         1277 :   tree images = NULL_TREE, stat = NULL_TREE,
    1350         1277 :        errmsg = NULL_TREE, errmsglen = NULL_TREE;
    1351              : 
    1352              :   /* Short cut: For single images without bound checking or without STAT=,
    1353              :      return early. (ERRMSG= is always untouched for -fcoarray=single.)  */
    1354         1277 :   if (!code->expr2 && !(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
    1355         1137 :       && flag_coarray != GFC_FCOARRAY_LIB)
    1356              :     return NULL_TREE;
    1357              : 
    1358          857 :   gfc_init_se (&se, NULL);
    1359          857 :   gfc_start_block (&se.pre);
    1360              : 
    1361          857 :   if (code->expr1 && code->expr1->rank == 0)
    1362              :     {
    1363           22 :       gfc_init_se (&argse, NULL);
    1364           22 :       gfc_conv_expr_val (&argse, code->expr1);
    1365           22 :       images = gfc_trans_force_lval (&argse.pre, argse.expr);
    1366           22 :       gfc_add_block_to_block (&se.pre, &argse.pre);
    1367              :     }
    1368              : 
    1369          857 :   if (code->expr2)
    1370              :     {
    1371           95 :       gcc_assert (code->expr2->expr_type == EXPR_VARIABLE
    1372              :                   || code->expr2->expr_type == EXPR_FUNCTION);
    1373           95 :       gfc_init_se (&argse, NULL);
    1374           95 :       gfc_conv_expr_val (&argse, code->expr2);
    1375           95 :       stat = argse.expr;
    1376           95 :       gfc_add_block_to_block (&se.pre, &argse.pre);
    1377              :     }
    1378              :   else
    1379          762 :     stat = null_pointer_node;
    1380              : 
    1381          857 :   if (code->expr3 && flag_coarray == GFC_FCOARRAY_LIB)
    1382              :     {
    1383           28 :       gcc_assert (code->expr3->expr_type == EXPR_VARIABLE
    1384              :                   || code->expr3->expr_type == EXPR_FUNCTION);
    1385           28 :       gfc_init_se (&argse, NULL);
    1386           28 :       argse.want_pointer = 1;
    1387           28 :       gfc_conv_expr (&argse, code->expr3);
    1388           28 :       gfc_conv_string_parameter (&argse);
    1389           28 :       errmsg = argse.expr;
    1390           28 :       errmsglen = fold_convert (size_type_node, argse.string_length);
    1391           28 :       gfc_add_block_to_block (&se.pre, &argse.pre);
    1392              :     }
    1393          829 :   else if (flag_coarray == GFC_FCOARRAY_LIB)
    1394              :     {
    1395          763 :       errmsg = null_pointer_node;
    1396          763 :       errmsglen = build_int_cst (size_type_node, 0);
    1397              :     }
    1398              : 
    1399              :   /* Check SYNC IMAGES(imageset) for valid image index.
    1400              :      FIXME: Add a check for image-set arrays.  */
    1401          857 :   if (code->expr1 && (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
    1402           24 :       && code->expr1->rank == 0)
    1403              :     {
    1404           18 :       tree images2 = fold_convert (integer_type_node, images);
    1405           18 :       tree cond;
    1406           18 :       if (flag_coarray != GFC_FCOARRAY_LIB)
    1407            5 :         cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
    1408            5 :                                 images, build_int_cst (TREE_TYPE (images), 1));
    1409              :       else
    1410              :         {
    1411           13 :           tree cond2;
    1412           13 :           tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
    1413              :                                      2, null_pointer_node, null_pointer_node);
    1414           13 :           cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
    1415              :                                   images2, tmp);
    1416           13 :           cond2 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
    1417              :                                    images,
    1418           13 :                                    build_int_cst (TREE_TYPE (images), 1));
    1419           13 :           cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
    1420              :                                   logical_type_node, cond, cond2);
    1421              :         }
    1422           18 :       gfc_trans_runtime_check (true, false, cond, &se.pre,
    1423           18 :                                &code->expr1->where, "Invalid image number "
    1424              :                                "%d in SYNC IMAGES", images2);
    1425              :     }
    1426              : 
    1427              :   /* Per F2008, 8.5.1, a SYNC MEMORY is implied by calling the
    1428              :      image control statements SYNC IMAGES and SYNC ALL.  */
    1429          857 :   if (flag_coarray == GFC_FCOARRAY_LIB)
    1430              :     {
    1431          791 :       tmp = gfc_build_string_const (strlen ("memory")+1, "memory"),
    1432          791 :       tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
    1433              :                         gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
    1434              :                         tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
    1435          791 :       ASM_VOLATILE_P (tmp) = 1;
    1436          791 :       gfc_add_expr_to_block (&se.pre, tmp);
    1437              :     }
    1438              : 
    1439          857 :   if (flag_coarray != GFC_FCOARRAY_LIB)
    1440              :     {
    1441              :       /* Set STAT to zero.  */
    1442           66 :       if (code->expr2)
    1443           52 :         gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
    1444              :     }
    1445          791 :   else if (type == EXEC_SYNC_ALL || type == EXEC_SYNC_MEMORY)
    1446              :     {
    1447              :       /* SYNC ALL           =>   stat == null_pointer_node
    1448              :          SYNC ALL(stat=s)   =>   stat has an integer type
    1449              : 
    1450              :          If "stat" has the wrong integer type, use a temp variable of
    1451              :          the right type and later cast the result back into "stat".  */
    1452          750 :       if (stat == null_pointer_node || TREE_TYPE (stat) == integer_type_node)
    1453              :         {
    1454          750 :           if (TREE_TYPE (stat) == integer_type_node)
    1455           27 :             stat = gfc_build_addr_expr (NULL, stat);
    1456              : 
    1457          750 :           if(type == EXEC_SYNC_MEMORY)
    1458           24 :             tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_memory,
    1459              :                                        3, stat, errmsg, errmsglen);
    1460              :           else
    1461          726 :             tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
    1462              :                                        3, stat, errmsg, errmsglen);
    1463              : 
    1464          750 :           gfc_add_expr_to_block (&se.pre, tmp);
    1465              :         }
    1466              :       else
    1467              :         {
    1468            0 :           tree tmp_stat = gfc_create_var (integer_type_node, "stat");
    1469              : 
    1470            0 :           tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
    1471              :                                      3, gfc_build_addr_expr (NULL, tmp_stat),
    1472              :                                      errmsg, errmsglen);
    1473            0 :           gfc_add_expr_to_block (&se.pre, tmp);
    1474              : 
    1475            0 :           gfc_add_modify (&se.pre, stat,
    1476            0 :                           fold_convert (TREE_TYPE (stat), tmp_stat));
    1477              :         }
    1478              :     }
    1479              :   else
    1480              :     {
    1481           41 :       tree len;
    1482              : 
    1483           41 :       gcc_assert (type == EXEC_SYNC_IMAGES);
    1484              : 
    1485           41 :       if (!code->expr1)
    1486              :         {
    1487           12 :           len = build_int_cst (integer_type_node, -1);
    1488           12 :           images = null_pointer_node;
    1489              :         }
    1490           29 :       else if (code->expr1->rank == 0)
    1491              :         {
    1492           17 :           len = integer_one_node;
    1493           17 :           images = gfc_build_addr_expr (NULL_TREE, images);
    1494              :         }
    1495              :       else
    1496              :         {
    1497              :           /* FIXME.  */
    1498           12 :           if (code->expr1->ts.kind != gfc_c_int_kind)
    1499            0 :             gfc_fatal_error ("Sorry, only support for integer kind %d "
    1500              :                              "implemented for image-set at %L",
    1501              :                              gfc_c_int_kind, &code->expr1->where);
    1502              : 
    1503           12 :           gfc_conv_array_parameter (&se, code->expr1, true, NULL, NULL, &len);
    1504           12 :           images = se.expr;
    1505              : 
    1506           12 :           tmp = gfc_typenode_for_spec (&code->expr1->ts);
    1507           12 :           if (GFC_ARRAY_TYPE_P (tmp) || GFC_DESCRIPTOR_TYPE_P (tmp))
    1508            0 :             tmp = gfc_get_element_type (tmp);
    1509              : 
    1510           24 :           len = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
    1511           12 :                                  TREE_TYPE (len), len,
    1512           12 :                                  fold_convert (TREE_TYPE (len),
    1513              :                                                TYPE_SIZE_UNIT (tmp)));
    1514           12 :           len = fold_convert (integer_type_node, len);
    1515              :         }
    1516              : 
    1517              :       /* SYNC IMAGES(imgs)        => stat == null_pointer_node
    1518              :          SYNC IMAGES(imgs,stat=s) => stat has an integer type
    1519              : 
    1520              :          If "stat" has the wrong integer type, use a temp variable of
    1521              :          the right type and later cast the result back into "stat".  */
    1522           41 :       if (stat == null_pointer_node || TREE_TYPE (stat) == integer_type_node)
    1523              :         {
    1524           41 :           if (TREE_TYPE (stat) == integer_type_node)
    1525           16 :             stat = gfc_build_addr_expr (NULL, stat);
    1526              : 
    1527           41 :           tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_images,
    1528              :                                      5, fold_convert (integer_type_node, len),
    1529              :                                      images, stat, errmsg, errmsglen);
    1530           41 :           gfc_add_expr_to_block (&se.pre, tmp);
    1531              :         }
    1532              :       else
    1533              :         {
    1534            0 :           tree tmp_stat = gfc_create_var (integer_type_node, "stat");
    1535              : 
    1536            0 :           tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_images,
    1537              :                                      5, fold_convert (integer_type_node, len),
    1538              :                                      images, gfc_build_addr_expr (NULL, tmp_stat),
    1539              :                                      errmsg, errmsglen);
    1540            0 :           gfc_add_expr_to_block (&se.pre, tmp);
    1541              : 
    1542            0 :           gfc_add_modify (&se.pre, stat,
    1543            0 :                           fold_convert (TREE_TYPE (stat), tmp_stat));
    1544              :         }
    1545              :     }
    1546              : 
    1547          857 :   return gfc_finish_block (&se.pre);
    1548              : }
    1549              : 
    1550              : 
    1551              : /* Generate GENERIC for the IF construct. This function also deals with
    1552              :    the simple IF statement, because the front end translates the IF
    1553              :    statement into an IF construct.
    1554              : 
    1555              :    We translate:
    1556              : 
    1557              :         IF (cond) THEN
    1558              :            then_clause
    1559              :         ELSEIF (cond2)
    1560              :            elseif_clause
    1561              :         ELSE
    1562              :            else_clause
    1563              :         ENDIF
    1564              : 
    1565              :    into:
    1566              : 
    1567              :         pre_cond_s;
    1568              :         if (cond_s)
    1569              :           {
    1570              :             then_clause;
    1571              :           }
    1572              :         else
    1573              :           {
    1574              :             pre_cond_s
    1575              :             if (cond_s)
    1576              :               {
    1577              :                 elseif_clause
    1578              :               }
    1579              :             else
    1580              :               {
    1581              :                 else_clause;
    1582              :               }
    1583              :           }
    1584              : 
    1585              :    where COND_S is the simplified version of the predicate. PRE_COND_S
    1586              :    are the pre side-effects produced by the translation of the
    1587              :    conditional.
    1588              :    We need to build the chain recursively otherwise we run into
    1589              :    problems with folding incomplete statements.  */
    1590              : 
    1591              : static tree
    1592       243703 : gfc_trans_if_1 (gfc_code * code)
    1593              : {
    1594       243703 :   gfc_se if_se;
    1595       243703 :   tree stmt, elsestmt;
    1596       243703 :   location_t loc, saved_loc = UNKNOWN_LOCATION;
    1597              : 
    1598              :   /* Check for an unconditional ELSE clause.  */
    1599       243703 :   if (!code->expr1)
    1600         6762 :     return gfc_trans_code (code->next);
    1601              : 
    1602              :   /* Initialize a statement builder for each block. Puts in NULL_TREEs.  */
    1603       236941 :   gfc_init_se (&if_se, NULL);
    1604       236941 :   gfc_start_block (&if_se.pre);
    1605              : 
    1606              :   /* Calculate the IF condition expression.  */
    1607       236941 :   if (GFC_LOCUS_IS_SET (code->expr1->where))
    1608              :     {
    1609       236941 :       saved_loc = input_location;
    1610       236941 :       input_location = gfc_get_location (&code->expr1->where);
    1611              :     }
    1612              : 
    1613       236941 :   gfc_conv_expr_val (&if_se, code->expr1);
    1614              : 
    1615       236941 :   if (saved_loc != UNKNOWN_LOCATION)
    1616       236941 :     input_location = saved_loc;
    1617              : 
    1618              :   /* Translate the THEN clause.  */
    1619       236941 :   stmt = gfc_trans_code (code->next);
    1620              : 
    1621              :   /* Translate the ELSE clause.  */
    1622       236941 :   if (code->block)
    1623         7004 :     elsestmt = gfc_trans_if_1 (code->block);
    1624              :   else
    1625       229937 :     elsestmt = build_empty_stmt (input_location);
    1626              : 
    1627              :   /* Build the condition expression and add it to the condition block.  */
    1628       473334 :   loc = (GFC_LOCUS_IS_SET (code->expr1->where)
    1629       473334 :          ? gfc_get_location (&code->expr1->where) : input_location);
    1630       236941 :   stmt = fold_build3_loc (loc, COND_EXPR, void_type_node, if_se.expr, stmt,
    1631              :                           elsestmt);
    1632              : 
    1633       236941 :   gfc_add_expr_to_block (&if_se.pre, stmt);
    1634              : 
    1635              :   /* Finish off this statement.  */
    1636       236941 :   return gfc_finish_block (&if_se.pre);
    1637              : }
    1638              : 
    1639              : tree
    1640       236699 : gfc_trans_if (gfc_code * code)
    1641              : {
    1642       236699 :   stmtblock_t body;
    1643       236699 :   tree exit_label;
    1644              : 
    1645              :   /* Create exit label so it is available for trans'ing the body code.  */
    1646       236699 :   exit_label = gfc_build_label_decl (NULL_TREE);
    1647       236699 :   code->exit_label = exit_label;
    1648              : 
    1649              :   /* Translate the actual code in code->block.  */
    1650       236699 :   gfc_init_block (&body);
    1651       236699 :   gfc_add_expr_to_block (&body, gfc_trans_if_1 (code->block));
    1652              : 
    1653              :   /* Add exit label.  */
    1654       236699 :   gfc_add_expr_to_block (&body, build1_v (LABEL_EXPR, exit_label));
    1655              : 
    1656       236699 :   return gfc_finish_block (&body);
    1657              : }
    1658              : 
    1659              : 
    1660              : /* Translate an arithmetic IF expression.
    1661              : 
    1662              :    IF (cond) label1, label2, label3 translates to
    1663              : 
    1664              :     if (cond <= 0)
    1665              :       {
    1666              :         if (cond < 0)
    1667              :           goto label1;
    1668              :         else // cond == 0
    1669              :           goto label2;
    1670              :       }
    1671              :     else // cond > 0
    1672              :       goto label3;
    1673              : 
    1674              :    An optimized version can be generated in case of equal labels.
    1675              :    E.g., if label1 is equal to label2, we can translate it to
    1676              : 
    1677              :     if (cond <= 0)
    1678              :       goto label1;
    1679              :     else
    1680              :       goto label3;
    1681              : */
    1682              : 
    1683              : tree
    1684           64 : gfc_trans_arithmetic_if (gfc_code * code)
    1685              : {
    1686           64 :   gfc_se se;
    1687           64 :   tree tmp;
    1688           64 :   tree branch1;
    1689           64 :   tree branch2;
    1690           64 :   tree zero;
    1691              : 
    1692              :   /* Start a new block.  */
    1693           64 :   gfc_init_se (&se, NULL);
    1694           64 :   gfc_start_block (&se.pre);
    1695              : 
    1696              :   /* Pre-evaluate COND.  */
    1697           64 :   gfc_conv_expr_val (&se, code->expr1);
    1698           64 :   se.expr = gfc_evaluate_now (se.expr, &se.pre);
    1699              : 
    1700              :   /* Build something to compare with.  */
    1701           64 :   zero = gfc_build_const (TREE_TYPE (se.expr), integer_zero_node);
    1702              : 
    1703           64 :   if (code->label1->value != code->label2->value)
    1704              :     {
    1705              :       /* If (cond < 0) take branch1 else take branch2.
    1706              :          First build jumps to the COND .LT. 0 and the COND .EQ. 0 cases.  */
    1707           49 :       branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
    1708           49 :       branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label2));
    1709              : 
    1710           49 :       if (code->label1->value != code->label3->value)
    1711           36 :         tmp = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
    1712              :                                se.expr, zero);
    1713              :       else
    1714           13 :         tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
    1715              :                                se.expr, zero);
    1716              : 
    1717           49 :       branch1 = fold_build3_loc (input_location, COND_EXPR, void_type_node,
    1718              :                                  tmp, branch1, branch2);
    1719              :     }
    1720              :   else
    1721           15 :     branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
    1722              : 
    1723           64 :   if (code->label1->value != code->label3->value
    1724           45 :       && code->label2->value != code->label3->value)
    1725              :     {
    1726              :       /* if (cond <= 0) take branch1 else take branch2.  */
    1727           37 :       branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label3));
    1728           37 :       tmp = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
    1729              :                              se.expr, zero);
    1730           37 :       branch1 = fold_build3_loc (input_location, COND_EXPR, void_type_node,
    1731              :                                  tmp, branch1, branch2);
    1732              :     }
    1733              : 
    1734              :   /* Append the COND_EXPR to the evaluation of COND, and return.  */
    1735           64 :   gfc_add_expr_to_block (&se.pre, branch1);
    1736           64 :   return gfc_finish_block (&se.pre);
    1737              : }
    1738              : 
    1739              : 
    1740              : /* Translate a CRITICAL block.  */
    1741              : 
    1742              : tree
    1743           37 : gfc_trans_critical (gfc_code *code)
    1744              :  {
    1745           37 :    stmtblock_t block;
    1746           37 :    tree tmp, token = NULL_TREE;
    1747           37 :    tree stat = NULL_TREE, errmsg, errmsg_len;
    1748              : 
    1749           37 :    gfc_start_block (&block);
    1750              : 
    1751           37 :    if (flag_coarray == GFC_FCOARRAY_LIB)
    1752              :      {
    1753           21 :        gfc_se se;
    1754              : 
    1755           21 :        gfc_init_se (&se, NULL);
    1756           21 :        gfc_trans_sync_stat (&code->ext.sync_stat, &se, &stat, &errmsg,
    1757              :                             &errmsg_len);
    1758           21 :        gfc_add_block_to_block (&block, &se.pre);
    1759              : 
    1760           21 :        token = gfc_get_symbol_decl (code->resolved_sym);
    1761           21 :        token = GFC_TYPE_ARRAY_CAF_TOKEN (TREE_TYPE (token));
    1762           21 :        tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_lock, 7,
    1763              :                                   token, integer_zero_node, integer_one_node,
    1764              :                                   null_pointer_node, stat, errmsg, errmsg_len);
    1765           21 :        gfc_add_expr_to_block (&block, tmp);
    1766           21 :        gfc_add_block_to_block (&block, &se.post);
    1767              : 
    1768              :        /* It guarantees memory consistency within the same segment.  */
    1769           21 :        tmp = gfc_build_string_const (strlen ("memory") + 1, "memory"),
    1770           21 :        tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
    1771              :                          gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
    1772              :                          tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
    1773           21 :        ASM_VOLATILE_P (tmp) = 1;
    1774              : 
    1775           21 :        gfc_add_expr_to_block (&block, tmp);
    1776              :     }
    1777              : 
    1778           37 :   tmp = gfc_trans_code (code->block->next);
    1779           37 :   gfc_add_expr_to_block (&block, tmp);
    1780              : 
    1781           37 :   if (flag_coarray == GFC_FCOARRAY_LIB)
    1782              :     {
    1783              :       /* END CRITICAL does not accept STAT or ERRMSG arguments.
    1784              :        * If STAT= is specified for CRITICAL, pass a stat argument to
    1785              :        * _gfortran_caf_lock_unlock to prevent termination in the event of an
    1786              :        * error, but ignore any value assigned to it.
    1787              :        */
    1788           21 :       tmp = build_call_expr_loc (
    1789              :         input_location, gfor_fndecl_caf_unlock, 6, token, integer_zero_node,
    1790              :         integer_one_node,
    1791           21 :         stat != NULL_TREE
    1792           21 :           ? gfc_build_addr_expr (NULL,
    1793              :                                  gfc_create_var (integer_type_node, "stat"))
    1794              :           : null_pointer_node,
    1795              :         null_pointer_node, integer_zero_node);
    1796           21 :       gfc_add_expr_to_block (&block, tmp);
    1797              : 
    1798              :       /* It guarantees memory consistency within the same segment */
    1799           21 :       tmp = gfc_build_string_const (strlen ("memory")+1, "memory"),
    1800           21 :         tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
    1801              :                           gfc_build_string_const (1, ""),
    1802              :                           NULL_TREE, NULL_TREE,
    1803              :                           tree_cons (NULL_TREE, tmp, NULL_TREE),
    1804              :                           NULL_TREE);
    1805           21 :       ASM_VOLATILE_P (tmp) = 1;
    1806              : 
    1807           21 :       gfc_add_expr_to_block (&block, tmp);
    1808              :     }
    1809              : 
    1810           37 :   return gfc_finish_block (&block);
    1811              : }
    1812              : 
    1813              : 
    1814              : /* Return true, when the class has a _len component.  */
    1815              : 
    1816              : static bool
    1817          746 : class_has_len_component (gfc_symbol *sym)
    1818              : {
    1819          746 :   gfc_component *comp = sym->ts.u.derived->components;
    1820         2168 :   while (comp)
    1821              :     {
    1822         1848 :       if (strcmp (comp->name, "_len") == 0)
    1823              :         return true;
    1824         1422 :       comp = comp->next;
    1825              :     }
    1826              :   return false;
    1827              : }
    1828              : 
    1829              : 
    1830              : static void
    1831         1720 : copy_descriptor (stmtblock_t *block, tree dst, tree src, int rank)
    1832              : {
    1833         1720 :   int n;
    1834         1720 :   tree dim;
    1835         1720 :   tree tmp;
    1836         1720 :   tree tmp2;
    1837         1720 :   tree size;
    1838         1720 :   tree offset;
    1839              : 
    1840         1720 :   offset = gfc_index_zero_node;
    1841              : 
    1842              :   /* Use memcpy to copy the descriptor. The size is the minimum of
    1843              :      the sizes of 'src' and 'dst'. This avoids a non-trivial conversion.  */
    1844         1720 :   tmp = TYPE_SIZE_UNIT (TREE_TYPE (src));
    1845         1720 :   tmp2 = TYPE_SIZE_UNIT (TREE_TYPE (dst));
    1846         1720 :   size = fold_build2_loc (input_location, MIN_EXPR,
    1847         1720 :                           TREE_TYPE (tmp), tmp, tmp2);
    1848         1720 :   tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
    1849         1720 :   tmp = build_call_expr_loc (input_location, tmp, 3,
    1850              :                              gfc_build_addr_expr (NULL_TREE, dst),
    1851              :                              gfc_build_addr_expr (NULL_TREE, src),
    1852              :                              fold_convert (size_type_node, size));
    1853         1720 :   gfc_add_expr_to_block (block, tmp);
    1854              : 
    1855              :   /* Set the offset correctly.  */
    1856         8592 :   for (n = 0; n < rank; n++)
    1857              :     {
    1858         5152 :       dim = gfc_rank_cst[n];
    1859         5152 :       tmp = gfc_conv_descriptor_lbound_get (src, dim);
    1860         5152 :       tmp2 = gfc_conv_descriptor_stride_get (src, dim);
    1861         5152 :       tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (tmp),
    1862              :                              tmp, tmp2);
    1863         5152 :       offset = fold_build2_loc (input_location, MINUS_EXPR,
    1864         5152 :                         TREE_TYPE (offset), offset, tmp);
    1865         5152 :       offset = gfc_evaluate_now (offset, block);
    1866              :     }
    1867              : 
    1868         1720 :   gfc_conv_descriptor_offset_set (block, dst, offset);
    1869         1720 : }
    1870              : 
    1871              : 
    1872              : /* Do proper initialization for ASSOCIATE names.  */
    1873              : 
    1874              : static void
    1875         7196 : trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
    1876              : {
    1877         7196 :   gfc_expr *e;
    1878         7196 :   tree tmp;
    1879         7196 :   bool class_target;
    1880         7196 :   bool unlimited;
    1881         7196 :   tree desc;
    1882         7196 :   tree charlen;
    1883         7196 :   bool need_len_assign;
    1884         7196 :   bool whole_array = true;
    1885         7196 :   bool same_class;
    1886         7196 :   gfc_ref *ref;
    1887         7196 :   gfc_symbol *sym2;
    1888              : 
    1889         7196 :   gcc_assert (sym->assoc);
    1890         7196 :   e = sym->assoc->target;
    1891              : 
    1892        16847 :   class_target = (e->expr_type == EXPR_VARIABLE)
    1893         6430 :                   && e->ts.type == BT_CLASS
    1894         9731 :                   && (gfc_is_class_scalar_expr (e)
    1895         1995 :                       || gfc_is_class_array_ref (e, NULL));
    1896         2455 :   same_class = class_target && sym->ts.type == BT_CLASS
    1897         1099 :                && strcmp (sym->ts.u.derived->name, e->ts.u.derived->name) == 0;
    1898              : 
    1899         7196 :   unlimited = UNLIMITED_POLY (e);
    1900              : 
    1901        15684 :   for (ref = e->ref; ref; ref = ref->next)
    1902         8548 :     if (ref->type == REF_ARRAY && ref->u.ar.type == AR_FULL
    1903         3358 :         && ref->u.ar.dimen != 0 && ref->next)
    1904              :       {
    1905              :         whole_array =  false;
    1906              :         break;
    1907              :       }
    1908              : 
    1909              :   /* Assignments to the string length need to be generated, when
    1910              :      ( sym is a char array or
    1911              :        sym has a _len component)
    1912              :      and the associated expression is unlimited polymorphic, which is
    1913              :      not (yet) correctly in 'unlimited', because for an already associated
    1914              :      BT_DERIVED the u-poly flag is not set, i.e.,
    1915              :       __tmp_CHARACTER_0_1 => w => arg
    1916              :        ^ generated temp      ^ from code, the w does not have the u-poly
    1917              :      flag set, where UNLIMITED_POLY(e) expects it.  */
    1918         5880 :   need_len_assign = ((unlimited || (e->ts.type == BT_DERIVED
    1919         2368 :                      && e->ts.u.derived->attr.unlimited_polymorphic))
    1920         2179 :       && (sym->ts.type == BT_CHARACTER
    1921         1443 :           || ((sym->ts.type == BT_CLASS || sym->ts.type == BT_DERIVED)
    1922          746 :               && class_has_len_component (sym)))
    1923         8358 :       && !sym->attr.select_rank_temporary);
    1924              : 
    1925              :   /* Do a `pointer assignment' with updated descriptor (or assign descriptor
    1926              :      to array temporary) for arrays with either unknown shape or if associating
    1927              :      to a variable. Select rank temporaries need somewhat different treatment
    1928              :      to other associate names and case temporaries. This because the selector
    1929              :      is assumed rank and so the offset in particular has to be changed. Also,
    1930              :      the case temporaries carry both allocatable and target attributes if
    1931              :      present in the selector. This means that an allocatation or change of
    1932              :      association can occur and so has to be dealt with.  */
    1933         7196 :   if (sym->attr.select_rank_temporary)
    1934              :     {
    1935         1362 :       gfc_se se;
    1936         1362 :       tree class_decl = NULL_TREE;
    1937         1362 :       int rank = 0;
    1938         1362 :       bool class_ptr;
    1939              : 
    1940         1362 :       sym2 = e->symtree->n.sym;
    1941         1362 :       gfc_init_se (&se, NULL);
    1942         1362 :       if (e->ts.type == BT_CLASS)
    1943              :         {
    1944              :           /* Go straight to the class data.  */
    1945          145 :           if (sym2->attr.dummy && !sym2->attr.optional)
    1946              :             {
    1947          121 :               class_decl = sym2->backend_decl;
    1948          121 :               if (DECL_LANG_SPECIFIC (class_decl)
    1949          121 :                   && GFC_DECL_SAVED_DESCRIPTOR (class_decl))
    1950            0 :                 class_decl = GFC_DECL_SAVED_DESCRIPTOR (class_decl);
    1951          121 :               if (POINTER_TYPE_P (TREE_TYPE (class_decl)))
    1952          121 :                 class_decl = build_fold_indirect_ref_loc (input_location,
    1953              :                                                           class_decl);
    1954          121 :               gcc_assert (GFC_CLASS_TYPE_P (TREE_TYPE (class_decl)));
    1955          121 :               se.expr = gfc_class_data_get (class_decl);
    1956              :             }
    1957              :           else
    1958              :             {
    1959           24 :               class_decl = sym2->backend_decl;
    1960           24 :               gfc_conv_expr_descriptor (&se, e);
    1961           24 :               if (POINTER_TYPE_P (TREE_TYPE (se.expr)))
    1962            0 :                 se.expr = build_fold_indirect_ref_loc (input_location,
    1963              :                                                        se.expr);
    1964              :             }
    1965              : 
    1966          145 :           if (CLASS_DATA (sym)->as && CLASS_DATA (sym)->as->rank > 0)
    1967          145 :             rank = CLASS_DATA (sym)->as->rank;
    1968              :         }
    1969              :       else
    1970              :         {
    1971         1217 :           gfc_conv_expr_descriptor (&se, e);
    1972         1217 :           if (sym->as && sym->as->rank > 0)
    1973         1168 :             rank = sym->as->rank;
    1974              :         }
    1975              : 
    1976         1362 :       desc = sym->backend_decl;
    1977              : 
    1978              :       /* The SELECT TYPE mechanisms turn class temporaries into pointers, which
    1979              :          point to the selector. */
    1980         1362 :       class_ptr = class_decl != NULL_TREE && POINTER_TYPE_P (TREE_TYPE (desc));
    1981          145 :       if (class_ptr)
    1982              :         {
    1983          145 :           tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (desc)), "class");
    1984          145 :           tmp = gfc_build_addr_expr (NULL, tmp);
    1985          145 :           gfc_add_modify (&se.pre, desc, tmp);
    1986              : 
    1987          145 :           tmp = gfc_class_vptr_get (class_decl);
    1988          145 :           gfc_add_modify (&se.pre, gfc_class_vptr_get (desc), tmp);
    1989          145 :           if (UNLIMITED_POLY (sym))
    1990          101 :             gfc_add_modify (&se.pre, gfc_class_len_get (desc),
    1991              :                             gfc_class_len_get (class_decl));
    1992              : 
    1993          145 :           desc = gfc_class_data_get (desc);
    1994              :         }
    1995              : 
    1996              :       /* SELECT RANK temporaries can carry the allocatable and pointer
    1997              :          attributes so the selector descriptor must be copied in and
    1998              :          copied out.  */
    1999         1362 :       if (rank > 0)
    2000         1282 :         copy_descriptor (&se.pre, desc, se.expr, rank);
    2001              :       else
    2002              :         {
    2003           80 :           tmp = gfc_conv_descriptor_data_get (se.expr);
    2004           80 :           gfc_add_modify (&se.pre, desc,
    2005           80 :                           fold_convert (TREE_TYPE (desc), tmp));
    2006              :         }
    2007              : 
    2008              :       /* Deal with associate_name => selector. Class associate names are
    2009              :          treated in the same way as in SELECT TYPE.  */
    2010         1362 :       sym2 = sym->assoc->target->symtree->n.sym;
    2011         1362 :       if (sym2->assoc && sym->assoc->target && sym2->ts.type != BT_CLASS)
    2012              :         {
    2013           54 :           sym2 = sym2->assoc->target->symtree->n.sym;
    2014           54 :           se.expr = sym2->backend_decl;
    2015              : 
    2016           54 :           if (POINTER_TYPE_P (TREE_TYPE (se.expr)))
    2017           54 :             se.expr = build_fold_indirect_ref_loc (input_location,
    2018              :                                                    se.expr);
    2019              :         }
    2020              : 
    2021              :       /* There could have been reallocation.  Copy descriptor back to the
    2022              :          selector and update the offset.  */
    2023         1362 :       if (sym->attr.allocatable || sym->attr.pointer
    2024          996 :           || (sym->ts.type == BT_CLASS
    2025          127 :               && (CLASS_DATA (sym)->attr.allocatable
    2026           79 :                   || CLASS_DATA (sym)->attr.pointer)))
    2027              :         {
    2028          493 :           if (rank > 0)
    2029          438 :             copy_descriptor (&se.post, se.expr, desc, rank);
    2030              :           else
    2031           55 :             gfc_conv_descriptor_data_set (&se.post, se.expr, desc);
    2032              : 
    2033              :           /* The dynamic type could have changed too.  */
    2034          493 :           if (sym->ts.type == BT_CLASS)
    2035              :             {
    2036          145 :               tmp = sym->backend_decl;
    2037          145 :               if (class_ptr)
    2038          145 :                 tmp = build_fold_indirect_ref_loc (input_location, tmp);
    2039          145 :               gfc_add_modify (&se.post, gfc_class_vptr_get (class_decl),
    2040              :                               gfc_class_vptr_get (tmp));
    2041          145 :               if (UNLIMITED_POLY (sym))
    2042          101 :                 gfc_add_modify (&se.post, gfc_class_len_get (class_decl),
    2043              :                                 gfc_class_len_get (tmp));
    2044              :             }
    2045              :         }
    2046              : 
    2047         1362 :       tmp = gfc_finish_block (&se.post);
    2048              : 
    2049         1362 :       gfc_add_init_cleanup (block, gfc_finish_block (&se.pre), tmp);
    2050              :     }
    2051              : 
    2052              :   /* Now all the other kinds of associate variable.  */
    2053              : 
    2054              :   /* First we do the F202y ASSOCIATE construct with an assumed rank selector.
    2055              :      Since this requires rank remapping, the simplest implementation builds an
    2056              :      array reference, using the array ref attached to the association_list,
    2057              :      followed by gfc_trans_pointer_assignment.  */
    2058         5834 :   else if (e->rank == -1 && sym->assoc->ar)
    2059              :     {
    2060           24 :       gfc_array_ref *ar;
    2061           24 :       gfc_expr *expr1 = gfc_lval_expr_from_sym (sym);
    2062           24 :       stmtblock_t init;
    2063           24 :       gfc_init_block (&init);
    2064              : 
    2065              :       /* Build the array reference and add to expr1.  */
    2066           24 :       gfc_free_ref_list (expr1->ref);
    2067           24 :       expr1->ref = gfc_get_ref();
    2068           24 :       expr1->ref->type = REF_ARRAY;
    2069           24 :       ar = gfc_copy_array_ref (sym->assoc->ar);
    2070           24 :       expr1->ref->u.ar = *ar;
    2071           24 :       expr1->ref->u.ar.type = AR_SECTION;
    2072              : 
    2073              :       /* For class objects, insert the _data component reference. Since the
    2074              :          associate-name is a pointer, it needs a target, which is created using
    2075              :          its typespec. If unlimited polymorphic, the _len field will be filled
    2076              :          by the pointer assignment.  */
    2077           24 :       if (expr1->ts.type == BT_CLASS)
    2078              :         {
    2079           12 :           need_len_assign = false;
    2080           12 :           gfc_ref *ref;
    2081           12 :           gfc_find_component (expr1->ts.u.derived, "_data", true, true, &ref);
    2082           12 :           ref->next = expr1->ref;
    2083           12 :           expr1->ref = ref;
    2084           12 :           expr1->rank = CLASS_DATA (sym)->as->rank;
    2085           12 :           tmp = gfc_create_var (gfc_typenode_for_spec (&sym->ts), "class");
    2086           12 :           tmp = gfc_build_addr_expr (NULL_TREE, tmp);
    2087           12 :           gfc_add_modify (&init, sym->backend_decl, tmp);
    2088              :         }
    2089              : 
    2090              :       /* Do the pointer assignment and clean up.  */
    2091           24 :       gfc_expr *expr2 = gfc_copy_expr (e);
    2092           24 :       gfc_add_expr_to_block (&init,
    2093              :                              gfc_trans_pointer_assignment (expr1, expr2));
    2094           24 :       gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL);
    2095           24 :       gfc_free_expr (expr1);
    2096           24 :       gfc_free_expr (expr2);
    2097           24 :     }
    2098              :   /* PDT array and string components are separately allocated for each element
    2099              :      of a PDT array. Therefore, there is no choice but to copy in and copy out
    2100              :      the target expression.  */
    2101         5810 :   else if (e && is_subref_array (e)
    2102          446 :            && (gfc_expr_attr (e).pdt_array || gfc_expr_attr (e).pdt_string))
    2103              :     {
    2104           18 :       gfc_se init;
    2105           18 :       gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (sym->backend_decl)));
    2106           18 :       gfc_init_se (&init, NULL);
    2107           18 :       gfc_conv_subref_array_arg (&init, e, false, INTENT_INOUT,
    2108           18 :                                  sym && sym->attr.pointer);
    2109           18 :       init.expr = build_fold_indirect_ref_loc (input_location, init.expr);
    2110           18 :       gfc_add_modify (&init.pre, sym->backend_decl, init.expr);
    2111           18 :       gfc_add_init_cleanup (block, gfc_finish_block (&init.pre),
    2112              :                             gfc_finish_block (&init.post));
    2113              :     }
    2114         5792 :   else if ((sym->attr.dimension || sym->attr.codimension) && !class_target
    2115          636 :            && (sym->as->type == AS_DEFERRED || sym->assoc->variable))
    2116              :     {
    2117          636 :       gfc_se se;
    2118          636 :       tree desc;
    2119          636 :       bool cst_array_ctor;
    2120          636 :       stmtblock_t init;
    2121          636 :       gfc_init_block (&init);
    2122              : 
    2123          636 :       desc = sym->backend_decl;
    2124         1272 :       cst_array_ctor = e->expr_type == EXPR_ARRAY
    2125           97 :               && gfc_constant_array_constructor_p (e->value.constructor)
    2126          654 :               && e->ts.type != BT_CHARACTER;
    2127              : 
    2128              :       /* If association is to an expression, evaluate it and create temporary.
    2129              :          Otherwise, get descriptor of target for pointer assignment.  */
    2130          636 :       gfc_init_se (&se, NULL);
    2131              : 
    2132          636 :       if (sym->assoc->variable || cst_array_ctor)
    2133              :         {
    2134          406 :           se.direct_byref = 1;
    2135          406 :           se.expr = desc;
    2136          406 :           GFC_DECL_PTR_ARRAY_P (sym->backend_decl) = 1;
    2137              :         }
    2138              : 
    2139          636 :       if (sym->attr.codimension)
    2140           16 :         se.want_coarray = 1;
    2141              : 
    2142          636 :       gfc_conv_expr_descriptor (&se, e);
    2143              : 
    2144          636 :       if (flag_coarray == GFC_FCOARRAY_LIB && sym->attr.codimension)
    2145              :         {
    2146            7 :           tree token = gfc_conv_descriptor_token (se.expr),
    2147              :                size
    2148            7 :                = sym->attr.dimension
    2149            7 :                    ? fold_build2 (MULT_EXPR, gfc_array_index_type,
    2150              :                                   gfc_conv_descriptor_size (se.expr, e->rank),
    2151              :                                   gfc_conv_descriptor_span_get (se.expr))
    2152            6 :                    : gfc_conv_descriptor_span_get (se.expr);
    2153              :           /* Create a new token, because in the token the modified descriptor
    2154              :              is stored.  The modified descriptor is needed for accesses on the
    2155              :              remote image.  In the scalar case, the base address needs to be
    2156              :              associated correctly, which also needs a new token.
    2157              :              The token is freed automatically be the end team statement.  */
    2158            7 :           gfc_add_expr_to_block (
    2159              :             &se.pre,
    2160              :             build_call_expr_loc (
    2161              :               input_location, gfor_fndecl_caf_register, 7, size,
    2162              :               build_int_cst (integer_type_node, GFC_CAF_COARRAY_MAP_EXISTING),
    2163              :               gfc_build_addr_expr (pvoid_type_node, token),
    2164              :               gfc_build_addr_expr (NULL_TREE, se.expr), null_pointer_node,
    2165              :               null_pointer_node, integer_zero_node));
    2166              :         }
    2167              : 
    2168          636 :       if (sym->ts.type == BT_CHARACTER
    2169          266 :           && !sym->attr.select_type_temporary
    2170          266 :           && sym->ts.u.cl->backend_decl
    2171          266 :           && VAR_P (sym->ts.u.cl->backend_decl)
    2172          222 :           && se.string_length
    2173          222 :           && se.string_length != sym->ts.u.cl->backend_decl)
    2174              :         {
    2175              :           /* When the target is a variable, its length is already known.  */
    2176          222 :           tree len = fold_convert (TREE_TYPE (sym->ts.u.cl->backend_decl),
    2177              :                                    se.string_length);
    2178          222 :           if (e->expr_type == EXPR_VARIABLE)
    2179          130 :             gfc_add_modify (&init, sym->ts.u.cl->backend_decl, len);
    2180              :           else
    2181           92 :             gfc_add_modify (&se.pre, sym->ts.u.cl->backend_decl, len);
    2182              :         }
    2183              : 
    2184              :       /* If we didn't already do the pointer assignment, set associate-name
    2185              :          descriptor to the one generated for the temporary.  */
    2186          636 :       if ((!sym->assoc->variable && !cst_array_ctor)
    2187          406 :           || !whole_array)
    2188              :         {
    2189          230 :           int dim;
    2190              : 
    2191          230 :           if (whole_array)
    2192          230 :             gfc_add_modify (&se.pre, desc, se.expr);
    2193              : 
    2194              :           /* The generated descriptor has lower bound zero (as array
    2195              :              temporary), shift bounds so we get lower bounds of 1.  */
    2196          579 :           for (dim = 0; dim < e->rank; ++dim)
    2197          301 :             gfc_conv_shift_descriptor_lbound (&se.pre, desc,
    2198              :                                               dim, gfc_index_one_node);
    2199              :         }
    2200              : 
    2201          636 :       if (e->expr_type == EXPR_FUNCTION && IS_PDT (e))
    2202              :         {
    2203            0 :           tmp = gfc_deallocate_pdt_comp (sym->ts.u.derived, se.expr,
    2204            0 :                                          sym->as->rank);
    2205            0 :           gfc_add_expr_to_block (&se.post, tmp);
    2206              :         }
    2207              : 
    2208              :       /* Done, register stuff as init / cleanup code.  */
    2209          636 :       gfc_add_block_to_block (&init, &se.pre);
    2210          636 :       gfc_add_init_cleanup (block, gfc_finish_block (&init),
    2211              :                             gfc_finish_block (&se.post));
    2212          636 :     }
    2213              : 
    2214              :   /* Temporaries, arising from TYPE IS, just need the descriptor of class
    2215              :      arrays to be assigned directly.  */
    2216         5156 :   else if (class_target && (sym->attr.dimension || sym->attr.codimension)
    2217         1356 :            && (sym->ts.type == BT_DERIVED || unlimited))
    2218              :     {
    2219         1356 :       gfc_se se;
    2220              : 
    2221         1356 :       gfc_init_se (&se, NULL);
    2222         1356 :       se.descriptor_only = 1;
    2223              :       /* In a select type the (temporary) associate variable shall point to
    2224              :          a standard fortran array (lower bound == 1), but conv_expr ()
    2225              :          just maps to the input array in the class object, whose lbound may
    2226              :          be arbitrary.  conv_expr_descriptor solves this by inserting a
    2227              :          temporary array descriptor.  */
    2228         1356 :       gfc_conv_expr_descriptor (&se, e);
    2229              : 
    2230         1356 :       gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr))
    2231              :                   || GFC_ARRAY_TYPE_P (TREE_TYPE (se.expr)));
    2232         1356 :       gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (sym->backend_decl)));
    2233              : 
    2234         1356 :       if (sym->ts.type == BT_CHARACTER)
    2235              :         {
    2236              :           /* Emit a DECL_EXPR for the variable sized array type in so the
    2237              :              gimplification of its type sizes works correctly.  */
    2238          302 :           tree arraytype;
    2239          302 :           tmp = TREE_TYPE (sym->backend_decl);
    2240          302 :           arraytype = TREE_TYPE (GFC_TYPE_ARRAY_DATAPTR_TYPE (tmp));
    2241          302 :           if (! TYPE_NAME (arraytype))
    2242           51 :             TYPE_NAME (arraytype) = build_decl (UNKNOWN_LOCATION, TYPE_DECL,
    2243              :                                                 NULL_TREE, arraytype);
    2244          302 :           gfc_add_expr_to_block (&se.pre, build1 (DECL_EXPR,
    2245          302 :                                  arraytype, TYPE_NAME (arraytype)));
    2246              :         }
    2247              : 
    2248         1356 :       if (GFC_ARRAY_TYPE_P (TREE_TYPE (se.expr)))
    2249              :         {
    2250            0 :           if (INDIRECT_REF_P (se.expr))
    2251            0 :             tmp = TREE_OPERAND (se.expr, 0);
    2252              :           else
    2253              :             tmp = se.expr;
    2254              : 
    2255            0 :           gfc_add_modify (&se.pre, sym->backend_decl,
    2256            0 :                           gfc_class_data_get (GFC_DECL_SAVED_DESCRIPTOR (tmp)));
    2257              :         }
    2258              :       else
    2259         1356 :         gfc_add_modify (&se.pre, sym->backend_decl, se.expr);
    2260              : 
    2261         1356 :       if (unlimited)
    2262              :         {
    2263              :           /* Recover the dtype, which has been overwritten by the
    2264              :              assignment from an unlimited polymorphic object.  */
    2265          829 :           tmp = gfc_conv_descriptor_dtype (sym->backend_decl);
    2266          829 :           gfc_add_modify (&se.pre, tmp,
    2267          829 :                           gfc_get_dtype (TREE_TYPE (sym->backend_decl)));
    2268              :         }
    2269              : 
    2270         1356 :       gfc_add_init_cleanup (block, gfc_finish_block (&se.pre),
    2271              :                             gfc_finish_block (&se.post));
    2272         1356 :     }
    2273              : 
    2274              :   /* Do a scalar pointer assignment; this is for scalar variable targets.  */
    2275         3800 :   else if (gfc_is_associate_pointer (sym))
    2276              :     {
    2277         3351 :       gfc_se se;
    2278              : 
    2279         3351 :       gcc_assert (!sym->attr.dimension && !sym->attr.codimension);
    2280              : 
    2281         3351 :       gfc_init_se (&se, NULL);
    2282              : 
    2283              :       /* Class associate-names come this way because they are
    2284              :          unconditionally associate pointers and the symbol is scalar.  */
    2285         3351 :       if (sym->ts.type == BT_CLASS && e->expr_type == EXPR_FUNCTION)
    2286              :         {
    2287           99 :           gfc_conv_expr (&se, e);
    2288           99 :           se.expr = gfc_evaluate_now (se.expr, &se.pre);
    2289              :           /* Finalize the expression and free if it is allocatable.  */
    2290           99 :           gfc_finalize_tree_expr (&se, NULL, gfc_expr_attr (e), e->rank);
    2291           99 :           gfc_add_block_to_block (&se.post, &se.finalblock);
    2292           99 :           need_len_assign = false;
    2293              :         }
    2294         3252 :       else if (sym->ts.type == BT_CLASS && CLASS_DATA (sym)->attr.dimension)
    2295              :         {
    2296          432 :           tree target_expr;
    2297              :           /* For a class array we need a descriptor for the selector.  */
    2298          432 :           gfc_conv_expr_descriptor (&se, e);
    2299              :           /* Needed to get/set the _len component below.  */
    2300          432 :           target_expr = se.expr;
    2301              : 
    2302              :           /* Obtain a temporary class container for the result.  */
    2303          432 :           gfc_conv_class_to_class (&se, e, sym->ts, false, true, false, false);
    2304          432 :           se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
    2305              : 
    2306          432 :           desc = gfc_class_data_get (se.expr);
    2307              : 
    2308          432 :           if (need_len_assign)
    2309              :             {
    2310          175 :               if (e->symtree
    2311          175 :                   && DECL_LANG_SPECIFIC (e->symtree->n.sym->backend_decl)
    2312           84 :                   && GFC_DECL_SAVED_DESCRIPTOR (e->symtree->n.sym->backend_decl)
    2313          205 :                   && TREE_CODE (target_expr) != COMPONENT_REF)
    2314              :                 /* Use the original class descriptor stored in the saved
    2315              :                    descriptor to get the target_expr.  */
    2316           36 :                 target_expr =
    2317           18 :                     GFC_DECL_SAVED_DESCRIPTOR (e->symtree->n.sym->backend_decl);
    2318              :               else
    2319              :                 /* Strip the _data component from the target_expr.  */
    2320          157 :                 target_expr = TREE_OPERAND (target_expr, 0);
    2321              :               /* Add a reference to the _len comp to the target expr.  */
    2322          175 :               tmp = gfc_class_len_get (target_expr);
    2323              :               /* Get the component-ref for the temp structure's _len comp.  */
    2324          175 :               charlen = gfc_class_len_get (se.expr);
    2325              :               /* Add the assign to the beginning of the block...  */
    2326          175 :               gfc_add_modify (&se.pre, charlen,
    2327          175 :                               fold_convert (TREE_TYPE (charlen), tmp));
    2328              :               /* and the oposite way at the end of the block, to hand changes
    2329              :                  on the string length back.  */
    2330          175 :               gfc_add_modify (&se.post, tmp,
    2331          175 :                               fold_convert (TREE_TYPE (tmp), charlen));
    2332              :               /* Length assignment done, prevent adding it again below.  */
    2333          175 :               need_len_assign = false;
    2334              :             }
    2335              :         }
    2336         2820 :       else if (sym->ts.type == BT_CLASS && e->ts.type == BT_CLASS
    2337          602 :                && CLASS_DATA (e)->attr.dimension)
    2338              :         {
    2339              :           /* This is bound to be a class array element.  */
    2340           80 :           gfc_conv_expr_reference (&se, e);
    2341              :           /* Obtain a temporary class container for the result.  */
    2342           80 :           gfc_conv_derived_to_class (&se, e, sym, se.expr, false, false,
    2343           80 :                                      e->symtree->name);
    2344           80 :           need_len_assign = false;
    2345              :         }
    2346         2740 :       else if (whole_array && (same_class || unlimited)
    2347          272 :                && e->ts.type == BT_CLASS && CLASS_DATA (e)->attr.codimension)
    2348              :         {
    2349           10 :           gfc_expr *class_e = gfc_find_and_cut_at_last_class_ref (e);
    2350           10 :           gfc_conv_expr (&se, class_e);
    2351           10 :           gfc_free_expr (class_e);
    2352           10 :           need_len_assign = false;
    2353           10 :         }
    2354              :       else
    2355              :         {
    2356              :           /* For BT_CLASS and BT_DERIVED, this boils down to a pointer assign,
    2357              :              which has the string length included.  For CHARACTERS it is still
    2358              :              needed and will be done at the end of this routine.  */
    2359         2730 :           gfc_conv_expr (&se, e);
    2360         2730 :           need_len_assign = need_len_assign && sym->ts.type == BT_CHARACTER;
    2361              :         }
    2362              : 
    2363         3351 :       if (sym->ts.type == BT_CHARACTER
    2364          525 :           && !sym->attr.select_type_temporary
    2365           91 :           && VAR_P (sym->ts.u.cl->backend_decl)
    2366           55 :           && se.string_length != sym->ts.u.cl->backend_decl)
    2367              :         {
    2368           55 :           gfc_add_modify (&se.pre, sym->ts.u.cl->backend_decl,
    2369           55 :                           fold_convert (TREE_TYPE (sym->ts.u.cl->backend_decl),
    2370              :                                         se.string_length));
    2371           55 :           if (e->expr_type == EXPR_FUNCTION)
    2372              :             {
    2373            6 :               tmp = gfc_call_free (sym->backend_decl);
    2374            6 :               gfc_add_expr_to_block (&se.post, tmp);
    2375              :             }
    2376              :         }
    2377              : 
    2378          525 :       if (sym->ts.type == BT_CHARACTER && e->ts.type == BT_CHARACTER
    2379         3442 :           && POINTER_TYPE_P (TREE_TYPE (se.expr)))
    2380              :         {
    2381              :           /* These are pointer types already.  */
    2382           73 :           tmp = fold_convert (TREE_TYPE (sym->backend_decl), se.expr);
    2383              :         }
    2384              :       else
    2385              :         {
    2386         3278 :           tree ctree = gfc_get_class_from_expr (se.expr);
    2387         3278 :           tmp = TREE_TYPE (sym->backend_decl);
    2388              : 
    2389         3278 :           if (sym->ts.type == BT_CLASS && e->ts.type == BT_CLASS)
    2390              :             {
    2391              :               /* F2018:19.5.1.6 "If a selector has the POINTER attribute,
    2392              :                  it shall be associated; the associate name is associated
    2393              :                  with the target of the pointer and does not have the
    2394              :                  POINTER attribute."  */
    2395          647 :               if (e->rank == 0 && ctree
    2396         1768 :                   && (!GFC_CLASS_TYPE_P (TREE_TYPE (se.expr))
    2397          564 :                       || CLASS_DATA (e)->attr.class_pointer))
    2398              :                 {
    2399          286 :                   tree stmp;
    2400          286 :                   tree dtmp;
    2401          286 :                   tree ctmp;
    2402              : 
    2403          286 :                   ctmp = ctree;
    2404          286 :                   dtmp = TREE_TYPE (TREE_TYPE (sym->backend_decl));
    2405          286 :                   ctree = gfc_create_var (dtmp, "class");
    2406              : 
    2407          286 :                   if (IS_INFERRED_TYPE (e)
    2408            6 :                       && !GFC_CLASS_TYPE_P (TREE_TYPE (se.expr)))
    2409              :                     stmp = se.expr;
    2410              :                   else
    2411          286 :                     stmp = gfc_class_data_get (ctmp);
    2412              : 
    2413          286 :                   if (!CLASS_DATA (sym)->attr.codimension
    2414          286 :                       && !POINTER_TYPE_P (TREE_TYPE (stmp)))
    2415            0 :                     stmp = gfc_build_addr_expr (NULL, stmp);
    2416              : 
    2417          286 :                   dtmp = gfc_class_data_get (ctree);
    2418          286 :                   stmp = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (dtmp), stmp);
    2419          286 :                   gfc_add_modify (&se.pre, dtmp, stmp);
    2420          286 :                   stmp = gfc_class_vptr_get (ctmp);
    2421          286 :                   dtmp = gfc_class_vptr_get (ctree);
    2422          286 :                   stmp = fold_convert (TREE_TYPE (dtmp), stmp);
    2423          286 :                   gfc_add_modify (&se.pre, dtmp, stmp);
    2424          286 :                   if (UNLIMITED_POLY (sym))
    2425              :                     {
    2426           66 :                       stmp = gfc_class_len_get (ctmp);
    2427           66 :                       dtmp = gfc_class_len_get (ctree);
    2428           66 :                       stmp = fold_convert (TREE_TYPE (dtmp), stmp);
    2429           66 :                       gfc_add_modify (&se.pre, dtmp, stmp);
    2430           66 :                       need_len_assign = false;
    2431              :                     }
    2432          286 :                   se.expr = ctree;
    2433              :                 }
    2434          835 :               else if (CLASS_DATA (sym)->attr.codimension)
    2435              :                 {
    2436           28 :                   gfc_conv_class_to_class (&se, e, sym->ts, false, false, false,
    2437              :                                            false);
    2438           28 :                   tmp = se.expr;
    2439              :                 }
    2440              :             }
    2441              :           /* For non-pointer types in se.expr, the first condition holds.
    2442              :              For pointer or reference types in se.expr, a double TREE_TYPE ()
    2443              :              is possible and an associate variable always is a pointer.  */
    2444         6527 :           if (!POINTER_TYPE_P (TREE_TYPE (se.expr))
    2445         3278 :               || TREE_TYPE (TREE_TYPE (se.expr))
    2446           29 :                    != TREE_TYPE (TREE_TYPE (sym->backend_decl)))
    2447         3250 :             tmp = gfc_build_addr_expr (tmp, se.expr);
    2448              :         }
    2449              : 
    2450         3351 :       gfc_add_modify (&se.pre, sym->backend_decl, tmp);
    2451              : 
    2452         3351 :       gfc_add_init_cleanup (block, gfc_finish_block( &se.pre),
    2453              :                             gfc_finish_block (&se.post));
    2454              :     }
    2455              : 
    2456              :   /* Do a simple assignment.  This is for scalar expressions, where we
    2457              :      can simply use expression assignment.  */
    2458              :   else
    2459              :     {
    2460          449 :       gfc_expr *lhs;
    2461          449 :       tree res;
    2462          449 :       gfc_se se;
    2463          449 :       stmtblock_t final_block;
    2464              : 
    2465          449 :       gfc_init_se (&se, NULL);
    2466              : 
    2467              :       /* resolve.cc converts some associate names to allocatable so that
    2468              :          allocation can take place automatically in gfc_trans_assignment.
    2469              :          The frontend prevents them from being either allocated,
    2470              :          deallocated or reallocated.  */
    2471          449 :       if (sym->ts.type == BT_DERIVED
    2472           90 :           && sym->ts.u.derived->attr.alloc_comp)
    2473              :         {
    2474           20 :           tmp = sym->backend_decl;
    2475           20 :           tmp = gfc_nullify_alloc_comp (sym->ts.u.derived, tmp,
    2476           20 :                                 sym->attr.dimension ? sym->as->rank : 0);
    2477           20 :           gfc_add_expr_to_block (&se.pre, tmp);
    2478              :         }
    2479              : 
    2480          449 :       if (sym->attr.allocatable)
    2481              :         {
    2482           12 :           tmp = sym->backend_decl;
    2483           12 :           if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)))
    2484            0 :             gfc_conv_descriptor_data_set (&se.pre, tmp, null_pointer_node);
    2485              :           else
    2486           12 :             gfc_add_modify (&se.pre, tmp,
    2487           12 :                             fold_convert (TREE_TYPE (tmp), null_pointer_node));
    2488              :         }
    2489              : 
    2490          449 :       lhs = gfc_lval_expr_from_sym (sym);
    2491          449 :       lhs->must_finalize = 0;
    2492          449 :       res = gfc_trans_assignment (lhs, e, false, true);
    2493          449 :       gfc_add_expr_to_block (&se.pre, res);
    2494              : 
    2495          449 :       gfc_init_block (&final_block);
    2496              : 
    2497          449 :       if (sym->attr.associate_var
    2498          449 :           && sym->ts.type == BT_DERIVED
    2499           90 :           && sym->ts.u.derived->attr.defined_assign_comp
    2500            0 :           && gfc_may_be_finalized (sym->ts)
    2501          449 :           && e->expr_type == EXPR_FUNCTION)
    2502              :         {
    2503            0 :           gfc_expr *ef;
    2504            0 :           ef = gfc_lval_expr_from_sym (sym);
    2505            0 :           gfc_add_finalizer_call (&final_block, ef);
    2506            0 :           gfc_free_expr (ef);
    2507              :         }
    2508              : 
    2509          449 :       if (sym->ts.type == BT_DERIVED
    2510           90 :           && sym->ts.u.derived->attr.alloc_comp)
    2511              :         {
    2512           20 :           tmp = sym->backend_decl;
    2513           20 :           tmp = gfc_deallocate_alloc_comp (sym->ts.u.derived,
    2514              :                                            tmp, 0);
    2515           20 :           gfc_add_expr_to_block (&final_block, tmp);
    2516              :         }
    2517              : 
    2518          449 :       tmp = sym->backend_decl;
    2519          449 :       if (e->expr_type == EXPR_FUNCTION && IS_PDT (sym))
    2520              :         {
    2521           14 :           tmp = gfc_deallocate_pdt_comp (sym->ts.u.derived, tmp,
    2522              :                                          0);
    2523              :         }
    2524          435 :       else if (e->expr_type == EXPR_FUNCTION && IS_CLASS_PDT (sym))
    2525              :         {
    2526            0 :           tmp = gfc_class_data_get (tmp);
    2527            0 :           tmp = gfc_deallocate_pdt_comp (CLASS_DATA (sym)->ts.u.derived,
    2528              :                                          tmp, 0);
    2529              :         }
    2530          435 :       else if (sym->attr.allocatable)
    2531              :         {
    2532           12 :           tmp = sym->backend_decl;
    2533              : 
    2534           12 :           if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)))
    2535            0 :             tmp = gfc_conv_descriptor_data_get (tmp);
    2536              : 
    2537              :           /* A simple call to free suffices here.  */
    2538           12 :           tmp = gfc_call_free (tmp);
    2539              : 
    2540              :           /* Make sure that reallocation on assignment cannot occur.  */
    2541           12 :           sym->attr.allocatable = 0;
    2542              :         }
    2543              :       else
    2544              :         tmp = NULL_TREE;
    2545              : 
    2546          449 :       gfc_add_expr_to_block (&final_block, tmp);
    2547          449 :       tmp = gfc_finish_block (&final_block);
    2548          449 :       res = gfc_finish_block (&se.pre);
    2549          449 :       gfc_add_init_cleanup (block, res, tmp);
    2550          449 :       gfc_free_expr (lhs);
    2551              :     }
    2552              : 
    2553              :   /* Set the stringlength, when needed.  */
    2554         7196 :   if (need_len_assign)
    2555              :     {
    2556          736 :       gfc_se se;
    2557          736 :       gfc_init_se (&se, NULL);
    2558          736 :       if (e->symtree->n.sym->ts.type == BT_CHARACTER)
    2559              :         {
    2560              :           /* Deferred strings are dealt with in the preceding.  */
    2561            0 :           gcc_assert (!e->symtree->n.sym->ts.deferred);
    2562            0 :           tmp = e->symtree->n.sym->ts.u.cl->backend_decl;
    2563              :         }
    2564          736 :       else if (e->symtree->n.sym->attr.function
    2565           12 :                && e->symtree->n.sym == e->symtree->n.sym->result)
    2566              :         {
    2567           12 :           tmp = gfc_get_fake_result_decl (e->symtree->n.sym, 0);
    2568           12 :           tmp = gfc_class_len_get (tmp);
    2569              :         }
    2570              :       else
    2571          724 :         tmp = gfc_class_len_get (gfc_get_symbol_decl (e->symtree->n.sym));
    2572          736 :       gfc_get_symbol_decl (sym);
    2573          736 :       charlen = sym->ts.type == BT_CHARACTER ? sym->ts.u.cl->backend_decl
    2574            0 :                                         : gfc_class_len_get (sym->backend_decl);
    2575              :       /* Prevent adding a noop len= len.  */
    2576          736 :       if (tmp != charlen)
    2577              :         {
    2578          736 :           gfc_add_modify (&se.pre, charlen,
    2579          736 :                           fold_convert (TREE_TYPE (charlen), tmp));
    2580          736 :           gfc_add_init_cleanup (block, gfc_finish_block (&se.pre),
    2581              :                                 gfc_finish_block (&se.post));
    2582              :         }
    2583              :     }
    2584         7196 : }
    2585              : 
    2586              : 
    2587              : /* Translate a BLOCK construct.  This is basically what we would do for a
    2588              :    procedure body.  */
    2589              : 
    2590              : tree
    2591        13848 : gfc_trans_block_construct (gfc_code* code)
    2592              : {
    2593        13848 :   gfc_namespace* ns;
    2594        13848 :   gfc_symbol* sym;
    2595        13848 :   gfc_wrapped_block block;
    2596        13848 :   tree exit_label;
    2597        13848 :   stmtblock_t body;
    2598        13848 :   gfc_association_list *ass;
    2599        13848 :   tree translated_body;
    2600              : 
    2601        13848 :   ns = code->ext.block.ns;
    2602        13848 :   gcc_assert (ns);
    2603        13848 :   sym = ns->proc_name;
    2604        13848 :   gcc_assert (sym);
    2605              : 
    2606              :   /* Process local variables.  */
    2607        13848 :   gcc_assert (!sym->tlink);
    2608        13848 :   sym->tlink = sym;
    2609        13848 :   gfc_process_block_locals (ns);
    2610              : 
    2611              :   /* Generate code including exit-label.  */
    2612        13848 :   gfc_init_block (&body);
    2613        13848 :   exit_label = gfc_build_label_decl (NULL_TREE);
    2614        13848 :   code->exit_label = exit_label;
    2615              : 
    2616        13848 :   finish_oacc_declare (ns, sym, true);
    2617              : 
    2618        13848 :   translated_body = gfc_trans_code (ns->code);
    2619        13848 :   if (ns->omp_structured_block)
    2620          457 :     translated_body = build1 (OMP_STRUCTURED_BLOCK, void_type_node,
    2621              :                               translated_body);
    2622        13848 :   gfc_add_expr_to_block (&body, translated_body);
    2623        13848 :   gfc_add_expr_to_block (&body, build1_v (LABEL_EXPR, exit_label));
    2624              : 
    2625              :   /* Finish everything.  */
    2626        13848 :   gfc_start_wrapped_block (&block, gfc_finish_block (&body));
    2627        13848 :   gfc_trans_deferred_vars (sym, &block);
    2628        21044 :   for (ass = code->ext.block.assoc; ass; ass = ass->next)
    2629         7196 :     trans_associate_var (ass->st->n.sym, &block);
    2630              : 
    2631        13848 :   return gfc_finish_wrapped_block (&block);
    2632              : }
    2633              : 
    2634              : /* Translate the simple DO construct in a C-style manner.
    2635              :    This is where the loop variable has integer type and step +-1.
    2636              :    Following code will generate infinite loop in case where TO is INT_MAX
    2637              :    (for +1 step) or INT_MIN (for -1 step)
    2638              : 
    2639              :    We translate a do loop from:
    2640              : 
    2641              :    DO dovar = from, to, step
    2642              :       body
    2643              :    END DO
    2644              : 
    2645              :    to:
    2646              : 
    2647              :    [Evaluate loop bounds and step]
    2648              :     dovar = from;
    2649              :     for (;;)
    2650              :       {
    2651              :         if (dovar > to)
    2652              :           goto end_label;
    2653              :         body;
    2654              :         cycle_label:
    2655              :         dovar += step;
    2656              :       }
    2657              :     end_label:
    2658              : 
    2659              :    This helps the optimizers by avoiding the extra pre-header condition and
    2660              :    we save a register as we just compare the updated IV (not a value in
    2661              :    previous step).  */
    2662              : 
    2663              : static tree
    2664        26233 : gfc_trans_simple_do (gfc_code * code, stmtblock_t *pblock, tree dovar,
    2665              :                      tree from, tree to, tree step, tree exit_cond)
    2666              : {
    2667        26233 :   stmtblock_t body;
    2668        26233 :   tree type;
    2669        26233 :   tree cond;
    2670        26233 :   tree tmp;
    2671        26233 :   tree saved_dovar = NULL;
    2672        26233 :   tree cycle_label;
    2673        26233 :   tree exit_label;
    2674        26233 :   location_t loc;
    2675        26233 :   type = TREE_TYPE (dovar);
    2676        26233 :   bool is_step_positive = tree_int_cst_sgn (step) > 0;
    2677              : 
    2678        26233 :   loc = gfc_get_location (&code->ext.iterator->start->where);
    2679              : 
    2680              :   /* Initialize the DO variable: dovar = from.  */
    2681        26233 :   gfc_add_modify_loc (loc, pblock, dovar,
    2682        26233 :                       fold_convert (TREE_TYPE (dovar), from));
    2683              : 
    2684              :   /* Save value for do-tinkering checking.  */
    2685        26233 :   if (gfc_option.rtcheck & GFC_RTCHECK_DO)
    2686              :     {
    2687          191 :       saved_dovar = gfc_create_var (type, ".saved_dovar");
    2688          191 :       gfc_add_modify_loc (loc, pblock, saved_dovar, dovar);
    2689              :     }
    2690              : 
    2691              :   /* Cycle and exit statements are implemented with gotos.  */
    2692        26233 :   cycle_label = gfc_build_label_decl (NULL_TREE);
    2693        26233 :   exit_label = gfc_build_label_decl (NULL_TREE);
    2694              : 
    2695              :   /* Put the labels where they can be found later.  See gfc_trans_do().  */
    2696        26233 :   code->cycle_label = cycle_label;
    2697        26233 :   code->exit_label = exit_label;
    2698              : 
    2699              :   /* Loop body.  */
    2700        26233 :   gfc_start_block (&body);
    2701              : 
    2702              :   /* Exit the loop if there is an I/O result condition or error.  */
    2703        26233 :   if (exit_cond)
    2704              :     {
    2705          322 :       tmp = build1_v (GOTO_EXPR, exit_label);
    2706          322 :       tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
    2707              :                              exit_cond, tmp,
    2708              :                              build_empty_stmt (loc));
    2709          322 :       gfc_add_expr_to_block (&body, tmp);
    2710              :     }
    2711              : 
    2712              :   /* Evaluate the loop condition.  */
    2713        26233 :   if (is_step_positive)
    2714        26119 :     cond = fold_build2_loc (loc, GT_EXPR, logical_type_node, dovar,
    2715              :                             fold_convert (type, to));
    2716              :   else
    2717          114 :     cond = fold_build2_loc (loc, LT_EXPR, logical_type_node, dovar,
    2718              :                             fold_convert (type, to));
    2719              : 
    2720        26233 :   cond = gfc_evaluate_now_loc (loc, cond, &body);
    2721        26233 :   if (code->ext.iterator->annot.unroll && cond != error_mark_node)
    2722           12 :     cond
    2723           12 :       = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
    2724              :                 build_int_cst (integer_type_node, annot_expr_unroll_kind),
    2725              :                 build_int_cst (integer_type_node,
    2726           12 :                                code->ext.iterator->annot.unroll));
    2727              : 
    2728        26233 :   if (code->ext.iterator->annot.ivdep && cond != error_mark_node)
    2729            2 :     cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
    2730              :                    build_int_cst (integer_type_node, annot_expr_ivdep_kind),
    2731              :                    integer_zero_node);
    2732        26233 :   if (code->ext.iterator->annot.vector && cond != error_mark_node)
    2733            2 :     cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
    2734              :                    build_int_cst (integer_type_node, annot_expr_vector_kind),
    2735              :                    integer_zero_node);
    2736        26233 :   if (code->ext.iterator->annot.novector && cond != error_mark_node)
    2737            2 :     cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
    2738              :                    build_int_cst (integer_type_node, annot_expr_no_vector_kind),
    2739              :                    integer_zero_node);
    2740              : 
    2741              :   /* The loop exit.  */
    2742        26233 :   tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label);
    2743        26233 :   TREE_USED (exit_label) = 1;
    2744        26233 :   tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
    2745              :                          cond, tmp, build_empty_stmt (loc));
    2746        26233 :   gfc_add_expr_to_block (&body, tmp);
    2747              : 
    2748              :   /* Check whether the induction variable is equal to INT_MAX
    2749              :      (respectively to INT_MIN).  */
    2750        26233 :   if (gfc_option.rtcheck & GFC_RTCHECK_DO)
    2751              :     {
    2752          191 :       tree boundary = is_step_positive ? TYPE_MAX_VALUE (type)
    2753          191 :         : TYPE_MIN_VALUE (type);
    2754              : 
    2755          191 :       tmp = fold_build2_loc (loc, EQ_EXPR, logical_type_node,
    2756              :                              dovar, boundary);
    2757          191 :       gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
    2758              :                                "Loop iterates infinitely");
    2759              :     }
    2760              : 
    2761              :   /* Main loop body.  */
    2762        26233 :   tmp = gfc_trans_code_cond (code->block->next, exit_cond);
    2763        26233 :   gfc_add_expr_to_block (&body, tmp);
    2764              : 
    2765              :   /* Label for cycle statements (if needed).  */
    2766        26233 :   if (TREE_USED (cycle_label))
    2767              :     {
    2768        26233 :       tmp = build1_v (LABEL_EXPR, cycle_label);
    2769        26233 :       gfc_add_expr_to_block (&body, tmp);
    2770              :     }
    2771              : 
    2772              :   /* Check whether someone has modified the loop variable.  */
    2773        26233 :   if (gfc_option.rtcheck & GFC_RTCHECK_DO)
    2774              :     {
    2775          191 :       tmp = fold_build2_loc (loc, NE_EXPR, logical_type_node,
    2776              :                              dovar, saved_dovar);
    2777          191 :       gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
    2778              :                                "Loop variable has been modified");
    2779              :     }
    2780              : 
    2781              :   /* Increment the loop variable.  */
    2782        26233 :   tmp = fold_build2_loc (loc, PLUS_EXPR, type, dovar, step);
    2783        26233 :   gfc_add_modify_loc (loc, &body, dovar, tmp);
    2784              : 
    2785        26233 :   if (gfc_option.rtcheck & GFC_RTCHECK_DO)
    2786          191 :     gfc_add_modify_loc (loc, &body, saved_dovar, dovar);
    2787              : 
    2788              :   /* Finish the loop body.  */
    2789        26233 :   tmp = gfc_finish_block (&body);
    2790        26233 :   tmp = fold_build1_loc (loc, LOOP_EXPR, void_type_node, tmp);
    2791              : 
    2792        26233 :   gfc_add_expr_to_block (pblock, tmp);
    2793              : 
    2794              :   /* Add the exit label.  */
    2795        26233 :   tmp = build1_v (LABEL_EXPR, exit_label);
    2796        26233 :   gfc_add_expr_to_block (pblock, tmp);
    2797              : 
    2798        26233 :   return gfc_finish_block (pblock);
    2799              : }
    2800              : 
    2801              : /* Translate the DO construct.  This obviously is one of the most
    2802              :    important ones to get right with any compiler, but especially
    2803              :    so for Fortran.
    2804              : 
    2805              :    We special case some loop forms as described in gfc_trans_simple_do.
    2806              :    For other cases we implement them with a separate loop count,
    2807              :    as described in the standard.
    2808              : 
    2809              :    We translate a do loop from:
    2810              : 
    2811              :    DO dovar = from, to, step
    2812              :       body
    2813              :    END DO
    2814              : 
    2815              :    to:
    2816              : 
    2817              :    [evaluate loop bounds and step]
    2818              :    empty = (step > 0 ? to < from : to > from);
    2819              :    countm1 = (to - from) / step;
    2820              :    dovar = from;
    2821              :    if (empty) goto exit_label;
    2822              :    for (;;)
    2823              :      {
    2824              :        body;
    2825              : cycle_label:
    2826              :        dovar += step
    2827              :        countm1t = countm1;
    2828              :        countm1--;
    2829              :        if (countm1t == 0) goto exit_label;
    2830              :      }
    2831              : exit_label:
    2832              : 
    2833              :    countm1 is an unsigned integer.  It is equal to the loop count minus one,
    2834              :    because the loop count itself can overflow.  */
    2835              : 
    2836              : tree
    2837        27316 : gfc_trans_do (gfc_code * code, tree exit_cond)
    2838              : {
    2839        27316 :   gfc_se se;
    2840        27316 :   tree dovar;
    2841        27316 :   tree saved_dovar = NULL;
    2842        27316 :   tree from;
    2843        27316 :   tree to;
    2844        27316 :   tree step;
    2845        27316 :   tree countm1;
    2846        27316 :   tree type;
    2847        27316 :   tree utype;
    2848        27316 :   tree cond;
    2849        27316 :   tree cycle_label;
    2850        27316 :   tree exit_label;
    2851        27316 :   tree tmp;
    2852        27316 :   stmtblock_t block;
    2853        27316 :   stmtblock_t body;
    2854        27316 :   location_t loc;
    2855              : 
    2856        27316 :   gfc_start_block (&block);
    2857              : 
    2858        27316 :   loc = gfc_get_location (&code->ext.iterator->start->where);
    2859              : 
    2860              :   /* Evaluate all the expressions in the iterator.  */
    2861        27316 :   gfc_init_se (&se, NULL);
    2862        27316 :   gfc_conv_expr_lhs (&se, code->ext.iterator->var);
    2863        27316 :   gfc_add_block_to_block (&block, &se.pre);
    2864        27316 :   dovar = se.expr;
    2865        27316 :   type = TREE_TYPE (dovar);
    2866              : 
    2867        27316 :   gfc_init_se (&se, NULL);
    2868        27316 :   gfc_conv_expr_val (&se, code->ext.iterator->start);
    2869        27316 :   gfc_add_block_to_block (&block, &se.pre);
    2870        27316 :   from = gfc_evaluate_now (se.expr, &block);
    2871              : 
    2872        27316 :   gfc_init_se (&se, NULL);
    2873        27316 :   gfc_conv_expr_val (&se, code->ext.iterator->end);
    2874        27316 :   gfc_add_block_to_block (&block, &se.pre);
    2875        27316 :   to = gfc_evaluate_now (se.expr, &block);
    2876              : 
    2877        27316 :   gfc_init_se (&se, NULL);
    2878        27316 :   gfc_conv_expr_val (&se, code->ext.iterator->step);
    2879        27316 :   gfc_add_block_to_block (&block, &se.pre);
    2880        27316 :   step = gfc_evaluate_now (se.expr, &block);
    2881              : 
    2882        27316 :   if (gfc_option.rtcheck & GFC_RTCHECK_DO)
    2883              :     {
    2884          203 :       tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, step,
    2885              :                              build_zero_cst (type));
    2886          203 :       gfc_trans_runtime_check (true, false, tmp, &block, &code->loc,
    2887              :                                "DO step value is zero");
    2888              :     }
    2889              : 
    2890              :   /* Special case simple loops.  */
    2891        27316 :   if (TREE_CODE (type) == INTEGER_TYPE
    2892        27316 :       && (integer_onep (step)
    2893         1115 :         || tree_int_cst_equal (step, integer_minus_one_node)))
    2894        26233 :     return gfc_trans_simple_do (code, &block, dovar, from, to, step,
    2895        26233 :                                 exit_cond);
    2896              : 
    2897         1083 :   if (TREE_CODE (type) == INTEGER_TYPE)
    2898         1001 :     utype = unsigned_type_for (type);
    2899              :   else
    2900           82 :     utype = unsigned_type_for (gfc_array_index_type);
    2901         1083 :   countm1 = gfc_create_var (utype, "countm1");
    2902              : 
    2903              :   /* Cycle and exit statements are implemented with gotos.  */
    2904         1083 :   cycle_label = gfc_build_label_decl (NULL_TREE);
    2905         1083 :   exit_label = gfc_build_label_decl (NULL_TREE);
    2906         1083 :   TREE_USED (exit_label) = 1;
    2907              : 
    2908              :   /* Put these labels where they can be found later.  */
    2909         1083 :   code->cycle_label = cycle_label;
    2910         1083 :   code->exit_label = exit_label;
    2911              : 
    2912              :   /* Initialize the DO variable: dovar = from.  */
    2913         1083 :   gfc_add_modify (&block, dovar, from);
    2914              : 
    2915              :   /* Save value for do-tinkering checking.  */
    2916         1083 :   if (gfc_option.rtcheck & GFC_RTCHECK_DO)
    2917              :     {
    2918           12 :       saved_dovar = gfc_create_var (type, ".saved_dovar");
    2919           12 :       gfc_add_modify_loc (loc, &block, saved_dovar, dovar);
    2920              :     }
    2921              : 
    2922              :   /* Initialize loop count and jump to exit label if the loop is empty.
    2923              :      This code is executed before we enter the loop body. We generate:
    2924              :      if (step > 0)
    2925              :        {
    2926              :          countm1 = (to - from) / step;
    2927              :          if (to < from)
    2928              :            goto exit_label;
    2929              :        }
    2930              :      else
    2931              :        {
    2932              :          countm1 = (from - to) / -step;
    2933              :          if (to > from)
    2934              :            goto exit_label;
    2935              :        }
    2936              :    */
    2937              : 
    2938         1083 :   if (TREE_CODE (type) == INTEGER_TYPE)
    2939              :     {
    2940         1001 :       tree pos, neg, tou, fromu, stepu, tmp2;
    2941              : 
    2942              :       /* The distance from FROM to TO cannot always be represented in a signed
    2943              :          type, thus use unsigned arithmetic, also to avoid any undefined
    2944              :          overflow issues.  */
    2945         1001 :       tou = fold_convert (utype, to);
    2946         1001 :       fromu = fold_convert (utype, from);
    2947         1001 :       stepu = fold_convert (utype, step);
    2948              : 
    2949              :       /* For a positive step, when to < from, exit, otherwise compute
    2950              :          countm1 = ((unsigned)to - (unsigned)from) / (unsigned)step  */
    2951         1001 :       tmp = fold_build2_loc (loc, LT_EXPR, logical_type_node, to, from);
    2952         1001 :       tmp2 = fold_build2_loc (loc, TRUNC_DIV_EXPR, utype,
    2953              :                               fold_build2_loc (loc, MINUS_EXPR, utype,
    2954              :                                                tou, fromu),
    2955              :                               stepu);
    2956         1001 :       pos = build2 (COMPOUND_EXPR, void_type_node,
    2957              :                     fold_build2 (MODIFY_EXPR, void_type_node,
    2958              :                                  countm1, tmp2),
    2959              :                     build3_loc (loc, COND_EXPR, void_type_node,
    2960              :                                 gfc_unlikely (tmp, PRED_FORTRAN_LOOP_PREHEADER),
    2961              :                                 build1_loc (loc, GOTO_EXPR, void_type_node,
    2962              :                                             exit_label), NULL_TREE));
    2963              : 
    2964              :       /* For a negative step, when to > from, exit, otherwise compute
    2965              :          countm1 = ((unsigned)from - (unsigned)to) / -(unsigned)step  */
    2966         1001 :       tmp = fold_build2_loc (loc, GT_EXPR, logical_type_node, to, from);
    2967         1001 :       tmp2 = fold_build2_loc (loc, TRUNC_DIV_EXPR, utype,
    2968              :                               fold_build2_loc (loc, MINUS_EXPR, utype,
    2969              :                                                fromu, tou),
    2970              :                               fold_build1_loc (loc, NEGATE_EXPR, utype, stepu));
    2971         1001 :       neg = build2 (COMPOUND_EXPR, void_type_node,
    2972              :                     fold_build2 (MODIFY_EXPR, void_type_node,
    2973              :                                  countm1, tmp2),
    2974              :                     build3_loc (loc, COND_EXPR, void_type_node,
    2975              :                                 gfc_unlikely (tmp, PRED_FORTRAN_LOOP_PREHEADER),
    2976              :                                 build1_loc (loc, GOTO_EXPR, void_type_node,
    2977              :                                             exit_label), NULL_TREE));
    2978              : 
    2979         1001 :       tmp = fold_build2_loc (loc, LT_EXPR, logical_type_node, step,
    2980         1001 :                              build_int_cst (TREE_TYPE (step), 0));
    2981         1001 :       tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp, neg, pos);
    2982              : 
    2983         1001 :       gfc_add_expr_to_block (&block, tmp);
    2984              :     }
    2985              :   else
    2986              :     {
    2987           82 :       tree pos_step;
    2988              : 
    2989              :       /* TODO: We could use the same width as the real type.
    2990              :          This would probably cause more problems that it solves
    2991              :          when we implement "long double" types.  */
    2992              : 
    2993           82 :       tmp = fold_build2_loc (loc, MINUS_EXPR, type, to, from);
    2994           82 :       tmp = fold_build2_loc (loc, RDIV_EXPR, type, tmp, step);
    2995           82 :       tmp = fold_build1_loc (loc, FIX_TRUNC_EXPR, utype, tmp);
    2996           82 :       gfc_add_modify (&block, countm1, tmp);
    2997              : 
    2998              :       /* We need a special check for empty loops:
    2999              :          empty = (step > 0 ? to < from : to > from);  */
    3000           82 :       pos_step = fold_build2_loc (loc, GT_EXPR, logical_type_node, step,
    3001              :                                   build_zero_cst (type));
    3002           82 :       tmp = fold_build3_loc (loc, COND_EXPR, logical_type_node, pos_step,
    3003              :                              fold_build2_loc (loc, LT_EXPR,
    3004              :                                               logical_type_node, to, from),
    3005              :                              fold_build2_loc (loc, GT_EXPR,
    3006              :                                               logical_type_node, to, from));
    3007              :       /* If the loop is empty, go directly to the exit label.  */
    3008           82 :       tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp,
    3009              :                          build1_v (GOTO_EXPR, exit_label),
    3010              :                          build_empty_stmt (input_location));
    3011           82 :       gfc_add_expr_to_block (&block, tmp);
    3012              :     }
    3013              : 
    3014              :   /* Loop body.  */
    3015         1083 :   gfc_start_block (&body);
    3016              : 
    3017              :   /* Main loop body.  */
    3018         1083 :   tmp = gfc_trans_code_cond (code->block->next, exit_cond);
    3019         1083 :   gfc_add_expr_to_block (&body, tmp);
    3020              : 
    3021              :   /* Label for cycle statements (if needed).  */
    3022         1083 :   if (TREE_USED (cycle_label))
    3023              :     {
    3024         1083 :       tmp = build1_v (LABEL_EXPR, cycle_label);
    3025         1083 :       gfc_add_expr_to_block (&body, tmp);
    3026              :     }
    3027              : 
    3028              :   /* Check whether someone has modified the loop variable.  */
    3029         1083 :   if (gfc_option.rtcheck & GFC_RTCHECK_DO)
    3030              :     {
    3031           12 :       tmp = fold_build2_loc (loc, NE_EXPR, logical_type_node, dovar,
    3032              :                              saved_dovar);
    3033           12 :       gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
    3034              :                                "Loop variable has been modified");
    3035              :     }
    3036              : 
    3037              :   /* Exit the loop if there is an I/O result condition or error.  */
    3038         1083 :   if (exit_cond)
    3039              :     {
    3040            1 :       tmp = build1_v (GOTO_EXPR, exit_label);
    3041            1 :       tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
    3042              :                              exit_cond, tmp,
    3043              :                              build_empty_stmt (input_location));
    3044            1 :       gfc_add_expr_to_block (&body, tmp);
    3045              :     }
    3046              : 
    3047              :   /* Increment the loop variable.  */
    3048         1083 :   tmp = fold_build2_loc (loc, PLUS_EXPR, type, dovar, step);
    3049         1083 :   gfc_add_modify_loc (loc, &body, dovar, tmp);
    3050              : 
    3051         1083 :   if (gfc_option.rtcheck & GFC_RTCHECK_DO)
    3052           12 :     gfc_add_modify_loc (loc, &body, saved_dovar, dovar);
    3053              : 
    3054              :   /* Initialize countm1t.  */
    3055         1083 :   tree countm1t = gfc_create_var (utype, "countm1t");
    3056         1083 :   gfc_add_modify_loc (loc, &body, countm1t, countm1);
    3057              : 
    3058              :   /* Decrement the loop count.  */
    3059         1083 :   tmp = fold_build2_loc (loc, MINUS_EXPR, utype, countm1,
    3060              :                          build_int_cst (utype, 1));
    3061         1083 :   gfc_add_modify_loc (loc, &body, countm1, tmp);
    3062              : 
    3063              :   /* End with the loop condition.  Loop until countm1t == 0.  */
    3064         1083 :   cond = fold_build2_loc (loc, EQ_EXPR, logical_type_node, countm1t,
    3065              :                           build_int_cst (utype, 0));
    3066         1083 :   if (code->ext.iterator->annot.unroll && cond != error_mark_node)
    3067            3 :     cond
    3068            3 :       = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
    3069              :                 build_int_cst (integer_type_node, annot_expr_unroll_kind),
    3070              :                 build_int_cst (integer_type_node,
    3071            3 :                                code->ext.iterator->annot.unroll));
    3072              : 
    3073         1083 :   if (code->ext.iterator->annot.ivdep && cond != error_mark_node)
    3074            0 :     cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
    3075              :                    build_int_cst (integer_type_node, annot_expr_ivdep_kind),
    3076              :                    integer_zero_node);
    3077         1083 :   if (code->ext.iterator->annot.vector && cond != error_mark_node)
    3078            0 :     cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
    3079              :                    build_int_cst (integer_type_node, annot_expr_vector_kind),
    3080              :                    integer_zero_node);
    3081         1083 :   if (code->ext.iterator->annot.novector && cond != error_mark_node)
    3082            0 :     cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
    3083              :                    build_int_cst (integer_type_node, annot_expr_no_vector_kind),
    3084              :                    integer_zero_node);
    3085              : 
    3086         1083 :   tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label);
    3087         1083 :   tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
    3088              :                          cond, tmp, build_empty_stmt (loc));
    3089         1083 :   gfc_add_expr_to_block (&body, tmp);
    3090              : 
    3091              :   /* End of loop body.  */
    3092         1083 :   tmp = gfc_finish_block (&body);
    3093              : 
    3094              :   /* The for loop itself.  */
    3095         1083 :   tmp = fold_build1_loc (loc, LOOP_EXPR, void_type_node, tmp);
    3096         1083 :   gfc_add_expr_to_block (&block, tmp);
    3097              : 
    3098              :   /* Add the exit label.  */
    3099         1083 :   tmp = build1_v (LABEL_EXPR, exit_label);
    3100         1083 :   gfc_add_expr_to_block (&block, tmp);
    3101              : 
    3102         1083 :   return gfc_finish_block (&block);
    3103              : }
    3104              : 
    3105              : 
    3106              : /* Translate the DO WHILE construct.
    3107              : 
    3108              :    We translate
    3109              : 
    3110              :    DO WHILE (cond)
    3111              :       body
    3112              :    END DO
    3113              : 
    3114              :    to:
    3115              : 
    3116              :    for ( ; ; )
    3117              :      {
    3118              :        pre_cond;
    3119              :        if (! cond) goto exit_label;
    3120              :        body;
    3121              : cycle_label:
    3122              :      }
    3123              : exit_label:
    3124              : 
    3125              :    Because the evaluation of the exit condition `cond' may have side
    3126              :    effects, we can't do much for empty loop bodies.  The backend optimizers
    3127              :    should be smart enough to eliminate any dead loops.  */
    3128              : 
    3129              : tree
    3130          502 : gfc_trans_do_while (gfc_code * code)
    3131              : {
    3132          502 :   gfc_se cond;
    3133          502 :   tree tmp;
    3134          502 :   tree cycle_label;
    3135          502 :   tree exit_label;
    3136          502 :   stmtblock_t block;
    3137              : 
    3138              :   /* Everything we build here is part of the loop body.  */
    3139          502 :   gfc_start_block (&block);
    3140              : 
    3141              :   /* Cycle and exit statements are implemented with gotos.  */
    3142          502 :   cycle_label = gfc_build_label_decl (NULL_TREE);
    3143          502 :   exit_label = gfc_build_label_decl (NULL_TREE);
    3144              : 
    3145              :   /* Put the labels where they can be found later. See gfc_trans_do().  */
    3146          502 :   code->cycle_label = cycle_label;
    3147          502 :   code->exit_label = exit_label;
    3148              : 
    3149              :   /* Create a GIMPLE version of the exit condition.  */
    3150          502 :   gfc_init_se (&cond, NULL);
    3151          502 :   gfc_conv_expr_val (&cond, code->expr1);
    3152          502 :   gfc_add_block_to_block (&block, &cond.pre);
    3153          502 :   cond.expr = fold_build1_loc (gfc_get_location (&code->expr1->where),
    3154          502 :                                TRUTH_NOT_EXPR, TREE_TYPE (cond.expr),
    3155              :                                cond.expr);
    3156              : 
    3157              :   /* Build "IF (! cond) GOTO exit_label".  */
    3158          502 :   tmp = build1_v (GOTO_EXPR, exit_label);
    3159          502 :   TREE_USED (exit_label) = 1;
    3160          502 :   tmp = fold_build3_loc (gfc_get_location (&code->expr1->where), COND_EXPR,
    3161              :                          void_type_node, cond.expr, tmp,
    3162              :                          build_empty_stmt (gfc_get_location (
    3163          502 :                                              &code->expr1->where)));
    3164          502 :   gfc_add_expr_to_block (&block, tmp);
    3165              : 
    3166              :   /* The main body of the loop.  */
    3167          502 :   tmp = gfc_trans_code (code->block->next);
    3168          502 :   gfc_add_expr_to_block (&block, tmp);
    3169              : 
    3170              :   /* Label for cycle statements (if needed).  */
    3171          502 :   if (TREE_USED (cycle_label))
    3172              :     {
    3173          502 :       tmp = build1_v (LABEL_EXPR, cycle_label);
    3174          502 :       gfc_add_expr_to_block (&block, tmp);
    3175              :     }
    3176              : 
    3177              :   /* End of loop body.  */
    3178          502 :   tmp = gfc_finish_block (&block);
    3179              : 
    3180          502 :   gfc_init_block (&block);
    3181              :   /* Build the loop.  */
    3182          502 :   tmp = fold_build1_loc (gfc_get_location (&code->expr1->where), LOOP_EXPR,
    3183              :                          void_type_node, tmp);
    3184          502 :   gfc_add_expr_to_block (&block, tmp);
    3185              : 
    3186              :   /* Add the exit label.  */
    3187          502 :   tmp = build1_v (LABEL_EXPR, exit_label);
    3188          502 :   gfc_add_expr_to_block (&block, tmp);
    3189              : 
    3190          502 :   return gfc_finish_block (&block);
    3191              : }
    3192              : 
    3193              : 
    3194              : /* Deal with the particular case of SELECT_TYPE, where the vtable
    3195              :    addresses are used for the selection. Since these are not sorted,
    3196              :    the selection has to be made by a series of if statements.  */
    3197              : 
    3198              : static tree
    3199         2922 : gfc_trans_select_type_cases (gfc_code * code)
    3200              : {
    3201         2922 :   gfc_code *c;
    3202         2922 :   gfc_case *cp;
    3203         2922 :   tree tmp;
    3204         2922 :   tree cond;
    3205         2922 :   tree low;
    3206         2922 :   tree high;
    3207         2922 :   gfc_se se;
    3208         2922 :   gfc_se cse;
    3209         2922 :   stmtblock_t block;
    3210         2922 :   stmtblock_t body;
    3211         2922 :   bool def = false;
    3212         2922 :   gfc_expr *e;
    3213         2922 :   gfc_start_block (&block);
    3214              : 
    3215              :   /* Calculate the switch expression.  */
    3216         2922 :   gfc_init_se (&se, NULL);
    3217         2922 :   gfc_conv_expr_val (&se, code->expr1);
    3218         2922 :   gfc_add_block_to_block (&block, &se.pre);
    3219              : 
    3220              :   /* Generate an expression for the selector hash value, for
    3221              :      use to resolve character cases.  */
    3222         2922 :   e = gfc_copy_expr (code->expr1->value.function.actual->expr);
    3223         2922 :   gfc_add_hash_component (e);
    3224              : 
    3225         2922 :   TREE_USED (code->exit_label) = 0;
    3226              : 
    3227         5844 : repeat:
    3228        16116 :   for (c = code->block; c; c = c->block)
    3229              :     {
    3230        10272 :       cp = c->ext.block.case_list;
    3231              : 
    3232              :       /* Assume it's the default case.  */
    3233        10272 :       low = NULL_TREE;
    3234        10272 :       high = NULL_TREE;
    3235        10272 :       tmp = NULL_TREE;
    3236              : 
    3237              :       /* Put the default case at the end.  */
    3238        10272 :       if ((!def && !cp->low) || (def && cp->low))
    3239         5136 :         continue;
    3240              : 
    3241         5136 :       if (cp->low && (cp->ts.type == BT_CLASS
    3242         3356 :                       || cp->ts.type == BT_DERIVED))
    3243              :         {
    3244         1923 :           gfc_init_se (&cse, NULL);
    3245         1923 :           gfc_conv_expr_val (&cse, cp->low);
    3246         1923 :           gfc_add_block_to_block (&block, &cse.pre);
    3247         1923 :           low = cse.expr;
    3248              :         }
    3249         3213 :       else if (cp->ts.type != BT_UNKNOWN)
    3250              :         {
    3251         1433 :           gcc_assert (cp->high);
    3252         1433 :           gfc_init_se (&cse, NULL);
    3253         1433 :           gfc_conv_expr_val (&cse, cp->high);
    3254         1433 :           gfc_add_block_to_block (&block, &cse.pre);
    3255         1433 :           high = cse.expr;
    3256              :         }
    3257              : 
    3258         5136 :       gfc_init_block (&body);
    3259              : 
    3260              :       /* Add the statements for this case.  */
    3261         5136 :       tmp = gfc_trans_code (c->next);
    3262         5136 :       gfc_add_expr_to_block (&body, tmp);
    3263              : 
    3264              :       /* Break to the end of the SELECT TYPE construct.  The default
    3265              :          case just falls through.  */
    3266         5136 :       if (!def)
    3267              :         {
    3268         3356 :           TREE_USED (code->exit_label) = 1;
    3269         3356 :           tmp = build1_v (GOTO_EXPR, code->exit_label);
    3270         3356 :           gfc_add_expr_to_block (&body, tmp);
    3271              :         }
    3272              : 
    3273         5136 :       tmp = gfc_finish_block (&body);
    3274              : 
    3275         5136 :       if (low != NULL_TREE)
    3276              :         {
    3277              :           /* Compare vtable pointers.  */
    3278         1923 :           cond = fold_build2_loc (input_location, EQ_EXPR,
    3279         1923 :                                   TREE_TYPE (se.expr), se.expr, low);
    3280         1923 :           tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
    3281              :                                  cond, tmp,
    3282              :                                  build_empty_stmt (input_location));
    3283              :         }
    3284         3213 :       else if (high != NULL_TREE)
    3285              :         {
    3286              :           /* Compare hash values for character cases.  */
    3287         1433 :           gfc_init_se (&cse, NULL);
    3288         1433 :           gfc_conv_expr_val (&cse, e);
    3289         1433 :           gfc_add_block_to_block (&block, &cse.pre);
    3290              : 
    3291         1433 :           cond = fold_build2_loc (input_location, EQ_EXPR,
    3292         1433 :                                   TREE_TYPE (se.expr), high, cse.expr);
    3293         1433 :           tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
    3294              :                                  cond, tmp,
    3295              :                                  build_empty_stmt (input_location));
    3296              :         }
    3297              : 
    3298         5136 :       gfc_add_expr_to_block (&block, tmp);
    3299              :     }
    3300              : 
    3301         5844 :   if (!def)
    3302              :     {
    3303         2922 :       def = true;
    3304         2922 :       goto repeat;
    3305              :     }
    3306              : 
    3307         2922 :   gfc_free_expr (e);
    3308              : 
    3309         2922 :   return gfc_finish_block (&block);
    3310              : }
    3311              : 
    3312              : 
    3313              : /* Translate the SELECT CASE construct for INTEGER case expressions,
    3314              :    without killing all potential optimizations.  The problem is that
    3315              :    Fortran allows unbounded cases, but the back-end does not, so we
    3316              :    need to intercept those before we enter the equivalent SWITCH_EXPR
    3317              :    we can build.
    3318              : 
    3319              :    For example, we translate this,
    3320              : 
    3321              :    SELECT CASE (expr)
    3322              :       CASE (:100,101,105:115)
    3323              :          block_1
    3324              :       CASE (190:199,200:)
    3325              :          block_2
    3326              :       CASE (300)
    3327              :          block_3
    3328              :       CASE DEFAULT
    3329              :          block_4
    3330              :    END SELECT
    3331              : 
    3332              :    to the GENERIC equivalent,
    3333              : 
    3334              :      switch (expr)
    3335              :        {
    3336              :          case (minimum value for typeof(expr) ... 100:
    3337              :          case 101:
    3338              :          case 105 ... 114:
    3339              :            block1:
    3340              :            goto end_label;
    3341              : 
    3342              :          case 200 ... (maximum value for typeof(expr):
    3343              :          case 190 ... 199:
    3344              :            block2;
    3345              :            goto end_label;
    3346              : 
    3347              :          case 300:
    3348              :            block_3;
    3349              :            goto end_label;
    3350              : 
    3351              :          default:
    3352              :            block_4;
    3353              :            goto end_label;
    3354              :        }
    3355              : 
    3356              :      end_label:  */
    3357              : 
    3358              : static tree
    3359          934 : gfc_trans_integer_select (gfc_code * code)
    3360              : {
    3361          934 :   gfc_code *c;
    3362          934 :   gfc_case *cp;
    3363          934 :   tree end_label;
    3364          934 :   tree tmp;
    3365          934 :   gfc_se se;
    3366          934 :   stmtblock_t block;
    3367          934 :   stmtblock_t body;
    3368              : 
    3369          934 :   gfc_start_block (&block);
    3370              : 
    3371              :   /* Calculate the switch expression.  */
    3372          934 :   gfc_init_se (&se, NULL);
    3373          934 :   gfc_conv_expr_val (&se, code->expr1);
    3374          934 :   gfc_add_block_to_block (&block, &se.pre);
    3375              : 
    3376          934 :   end_label = gfc_build_label_decl (NULL_TREE);
    3377              : 
    3378          934 :   gfc_init_block (&body);
    3379              : 
    3380         2818 :   for (c = code->block; c; c = c->block)
    3381              :     {
    3382         3840 :       for (cp = c->ext.block.case_list; cp; cp = cp->next)
    3383              :         {
    3384         1956 :           tree low, high;
    3385         1956 :           tree label;
    3386              : 
    3387              :           /* Assume it's the default case.  */
    3388         1956 :           low = high = NULL_TREE;
    3389              : 
    3390         1956 :           if (cp->low)
    3391              :             {
    3392         1555 :               if (cp->low->ts.type == BT_INTEGER)
    3393         1513 :                 low = gfc_conv_mpz_to_tree (cp->low->value.integer,
    3394              :                                             cp->low->ts.kind);
    3395              :               else
    3396           42 :                 low = gfc_conv_mpz_unsigned_to_tree (cp->low->value.integer,
    3397              :                                                      cp->low->ts.kind);
    3398              : 
    3399              :               /* If there's only a lower bound, set the high bound to the
    3400              :                  maximum value of the case expression.  */
    3401         1555 :               if (!cp->high)
    3402           45 :                 high = TYPE_MAX_VALUE (TREE_TYPE (se.expr));
    3403              :             }
    3404              : 
    3405         1956 :           if (cp->high)
    3406              :             {
    3407              :               /* Three cases are possible here:
    3408              : 
    3409              :                  1) There is no lower bound, e.g. CASE (:N).
    3410              :                  2) There is a lower bound .NE. high bound, that is
    3411              :                     a case range, e.g. CASE (N:M) where M>N (we make
    3412              :                     sure that M>N during type resolution).
    3413              :                  3) There is a lower bound, and it has the same value
    3414              :                     as the high bound, e.g. CASE (N:N).  This is our
    3415              :                     internal representation of CASE(N).
    3416              : 
    3417              :                  In the first and second case, we need to set a value for
    3418              :                  high.  In the third case, we don't because the GCC middle
    3419              :                  end represents a single case value by just letting high be
    3420              :                  a NULL_TREE.  We can't do that because we need to be able
    3421              :                  to represent unbounded cases.  */
    3422              : 
    3423         1554 :               if (!cp->low
    3424         1510 :                   || (mpz_cmp (cp->low->value.integer,
    3425         1510 :                                 cp->high->value.integer) != 0))
    3426              :                 {
    3427           73 :                   if (cp->high->ts.type == BT_INTEGER)
    3428           73 :                     high = gfc_conv_mpz_to_tree (cp->high->value.integer,
    3429              :                                                  cp->high->ts.kind);
    3430              :                   else
    3431            0 :                     high
    3432            0 :                       = gfc_conv_mpz_unsigned_to_tree (cp->high->value.integer,
    3433              :                                                        cp->high->ts.kind);
    3434              :                 }
    3435              : 
    3436              :               /* Unbounded case.  */
    3437         1554 :               if (!cp->low)
    3438           44 :                 low = TYPE_MIN_VALUE (TREE_TYPE (se.expr));
    3439              :             }
    3440              : 
    3441              :           /* Build a label.  */
    3442         1956 :           label = gfc_build_label_decl (NULL_TREE);
    3443              : 
    3444              :           /* Add this case label.
    3445              :              Add parameter 'label', make it match GCC backend.  */
    3446         1956 :           tmp = build_case_label (low, high, label);
    3447         1956 :           gfc_add_expr_to_block (&body, tmp);
    3448              :         }
    3449              : 
    3450              :       /* Add the statements for this case.  */
    3451         1884 :       tmp = gfc_trans_code (c->next);
    3452         1884 :       gfc_add_expr_to_block (&body, tmp);
    3453              : 
    3454              :       /* Break to the end of the construct.  */
    3455         1884 :       tmp = build1_v (GOTO_EXPR, end_label);
    3456         1884 :       gfc_add_expr_to_block (&body, tmp);
    3457              :     }
    3458              : 
    3459          934 :   tmp = gfc_finish_block (&body);
    3460          934 :   tmp = fold_build2_loc (input_location, SWITCH_EXPR, NULL_TREE, se.expr, tmp);
    3461          934 :   gfc_add_expr_to_block (&block, tmp);
    3462              : 
    3463          934 :   tmp = build1_v (LABEL_EXPR, end_label);
    3464          934 :   gfc_add_expr_to_block (&block, tmp);
    3465              : 
    3466          934 :   return gfc_finish_block (&block);
    3467              : }
    3468              : 
    3469              : 
    3470              : /* Translate the SELECT CASE construct for LOGICAL case expressions.
    3471              : 
    3472              :    There are only two cases possible here, even though the standard
    3473              :    does allow three cases in a LOGICAL SELECT CASE construct: .TRUE.,
    3474              :    .FALSE., and DEFAULT.
    3475              : 
    3476              :    We never generate more than two blocks here.  Instead, we always
    3477              :    try to eliminate the DEFAULT case.  This way, we can translate this
    3478              :    kind of SELECT construct to a simple
    3479              : 
    3480              :    if {} else {};
    3481              : 
    3482              :    expression in GENERIC.  */
    3483              : 
    3484              : static tree
    3485           54 : gfc_trans_logical_select (gfc_code * code)
    3486              : {
    3487           54 :   gfc_code *c;
    3488           54 :   gfc_code *t, *f, *d;
    3489           54 :   gfc_case *cp;
    3490           54 :   gfc_se se;
    3491           54 :   stmtblock_t block;
    3492              : 
    3493              :   /* Assume we don't have any cases at all.  */
    3494           54 :   t = f = d = NULL;
    3495              : 
    3496              :   /* Now see which ones we actually do have.  We can have at most two
    3497              :      cases in a single case list: one for .TRUE. and one for .FALSE.
    3498              :      The default case is always separate.  If the cases for .TRUE. and
    3499              :      .FALSE. are in the same case list, the block for that case list
    3500              :      always executed, and we don't generate code a COND_EXPR.  */
    3501          171 :   for (c = code->block; c; c = c->block)
    3502              :     {
    3503          243 :       for (cp = c->ext.block.case_list; cp; cp = cp->next)
    3504              :         {
    3505          126 :           if (cp->low)
    3506              :             {
    3507           72 :               if (cp->low->value.logical == 0) /* .FALSE.  */
    3508              :                 f = c;
    3509              :               else /* if (cp->value.logical != 0), thus .TRUE.  */
    3510           36 :                 t = c;
    3511              :             }
    3512              :           else
    3513              :             d = c;
    3514              :         }
    3515              :     }
    3516              : 
    3517              :   /* Start a new block.  */
    3518           54 :   gfc_start_block (&block);
    3519              : 
    3520              :   /* Calculate the switch expression.  We always need to do this
    3521              :      because it may have side effects.  */
    3522           54 :   gfc_init_se (&se, NULL);
    3523           54 :   gfc_conv_expr_val (&se, code->expr1);
    3524           54 :   gfc_add_block_to_block (&block, &se.pre);
    3525              : 
    3526           54 :   if (t == f && t != NULL)
    3527              :     {
    3528              :       /* Cases for .TRUE. and .FALSE. are in the same block.  Just
    3529              :          translate the code for these cases, append it to the current
    3530              :          block.  */
    3531            9 :       gfc_add_expr_to_block (&block, gfc_trans_code (t->next));
    3532              :     }
    3533              :   else
    3534              :     {
    3535           45 :       tree true_tree, false_tree, stmt;
    3536              : 
    3537           45 :       true_tree = build_empty_stmt (input_location);
    3538           45 :       false_tree = build_empty_stmt (input_location);
    3539              : 
    3540              :       /* If we have a case for .TRUE. and for .FALSE., discard the default case.
    3541              :           Otherwise, if .TRUE. or .FALSE. is missing and there is a default case,
    3542              :           make the missing case the default case.  */
    3543           45 :       if (t != NULL && f != NULL)
    3544           63 :         d = NULL;
    3545           36 :       else if (d != NULL)
    3546              :         {
    3547           36 :           if (t == NULL)
    3548              :             t = d;
    3549              :           else
    3550              :             f = d;
    3551              :         }
    3552              : 
    3553              :       /* Translate the code for each of these blocks, and append it to
    3554              :          the current block.  */
    3555           18 :       if (t != NULL)
    3556           45 :         true_tree = gfc_trans_code (t->next);
    3557              : 
    3558           45 :       if (f != NULL)
    3559           45 :         false_tree = gfc_trans_code (f->next);
    3560              : 
    3561           45 :       stmt = fold_build3_loc (input_location, COND_EXPR, void_type_node,
    3562              :                               se.expr, true_tree, false_tree);
    3563           45 :       gfc_add_expr_to_block (&block, stmt);
    3564              :     }
    3565              : 
    3566           54 :   return gfc_finish_block (&block);
    3567              : }
    3568              : 
    3569              : 
    3570              : /* The jump table types are stored in static variables to avoid
    3571              :    constructing them from scratch every single time.  */
    3572              : static GTY(()) tree select_struct[2];
    3573              : 
    3574              : /* Translate the SELECT CASE construct for CHARACTER case expressions.
    3575              :    Instead of generating compares and jumps, it is far simpler to
    3576              :    generate a data structure describing the cases in order and call a
    3577              :    library subroutine that locates the right case.
    3578              :    This is particularly true because this is the only case where we
    3579              :    might have to dispose of a temporary.
    3580              :    The library subroutine returns a pointer to jump to or NULL if no
    3581              :    branches are to be taken.  */
    3582              : 
    3583              : static tree
    3584           75 : gfc_trans_character_select (gfc_code *code)
    3585              : {
    3586           75 :   tree init, end_label, tmp, type, case_num, label, fndecl;
    3587           75 :   stmtblock_t block, body;
    3588           75 :   gfc_case *cp, *d;
    3589           75 :   gfc_code *c;
    3590           75 :   gfc_se se, expr1se;
    3591           75 :   int n, k;
    3592           75 :   vec<constructor_elt, va_gc> *inits = NULL;
    3593              : 
    3594           75 :   tree pchartype = gfc_get_pchar_type (code->expr1->ts.kind);
    3595              : 
    3596              :   /* The jump table types are stored in static variables to avoid
    3597              :      constructing them from scratch every single time.  */
    3598           75 :   static tree ss_string1[2], ss_string1_len[2];
    3599           75 :   static tree ss_string2[2], ss_string2_len[2];
    3600           75 :   static tree ss_target[2];
    3601              : 
    3602           75 :   cp = code->block->ext.block.case_list;
    3603          241 :   while (cp->left != NULL)
    3604              :     cp = cp->left;
    3605              : 
    3606              :   /* Generate the body */
    3607           75 :   gfc_start_block (&block);
    3608           75 :   gfc_init_se (&expr1se, NULL);
    3609           75 :   gfc_conv_expr_reference (&expr1se, code->expr1);
    3610              : 
    3611           75 :   gfc_add_block_to_block (&block, &expr1se.pre);
    3612              : 
    3613           75 :   end_label = gfc_build_label_decl (NULL_TREE);
    3614              : 
    3615           75 :   gfc_init_block (&body);
    3616              : 
    3617              :   /* Attempt to optimize length 1 selects.  */
    3618           75 :   if (integer_onep (expr1se.string_length))
    3619              :     {
    3620          126 :       for (d = cp; d; d = d->right)
    3621              :         {
    3622          110 :           gfc_charlen_t i;
    3623          110 :           if (d->low)
    3624              :             {
    3625          100 :               gcc_assert (d->low->expr_type == EXPR_CONSTANT
    3626              :                           && d->low->ts.type == BT_CHARACTER);
    3627          100 :               if (d->low->value.character.length > 1)
    3628              :                 {
    3629            2 :                   for (i = 1; i < d->low->value.character.length; i++)
    3630            2 :                     if (d->low->value.character.string[i] != ' ')
    3631              :                       break;
    3632            2 :                   if (i != d->low->value.character.length)
    3633              :                     {
    3634            2 :                       if (optimize && d->high && i == 1)
    3635              :                         {
    3636            2 :                           gcc_assert (d->high->expr_type == EXPR_CONSTANT
    3637              :                                       && d->high->ts.type == BT_CHARACTER);
    3638            2 :                           if (d->high->value.character.length > 1
    3639            2 :                               && (d->low->value.character.string[0]
    3640            2 :                                   == d->high->value.character.string[0])
    3641            2 :                               && d->high->value.character.string[1] != ' '
    3642            4 :                               && ((d->low->value.character.string[1] < ' ')
    3643              :                                   == (d->high->value.character.string[1]
    3644            2 :                                       < ' ')))
    3645            2 :                             continue;
    3646              :                         }
    3647              :                       break;
    3648              :                     }
    3649              :                 }
    3650              :             }
    3651          108 :           if (d->high)
    3652              :             {
    3653           98 :               gcc_assert (d->high->expr_type == EXPR_CONSTANT
    3654              :                           && d->high->ts.type == BT_CHARACTER);
    3655           98 :               if (d->high->value.character.length > 1)
    3656              :                 {
    3657            3 :                   for (i = 1; i < d->high->value.character.length; i++)
    3658            2 :                     if (d->high->value.character.string[i] != ' ')
    3659              :                       break;
    3660            1 :                   if (i != d->high->value.character.length)
    3661              :                     break;
    3662              :                 }
    3663              :             }
    3664              :         }
    3665           16 :       if (d == NULL)
    3666              :         {
    3667           16 :           tree ctype = gfc_get_char_type (code->expr1->ts.kind);
    3668              : 
    3669           58 :           for (c = code->block; c; c = c->block)
    3670              :             {
    3671          152 :               for (cp = c->ext.block.case_list; cp; cp = cp->next)
    3672              :                 {
    3673          110 :                   tree low, high;
    3674          110 :                   tree label;
    3675          110 :                   gfc_char_t r;
    3676              : 
    3677              :                   /* Assume it's the default case.  */
    3678          110 :                   low = high = NULL_TREE;
    3679              : 
    3680          110 :                   if (cp->low)
    3681              :                     {
    3682              :                       /* CASE ('ab') or CASE ('ab':'az') will never match
    3683              :                          any length 1 character.  */
    3684          100 :                       if (cp->low->value.character.length > 1
    3685            2 :                           && cp->low->value.character.string[1] != ' ')
    3686            2 :                         continue;
    3687              : 
    3688           98 :                       if (cp->low->value.character.length > 0)
    3689           97 :                         r = cp->low->value.character.string[0];
    3690              :                       else
    3691              :                         r = ' ';
    3692           98 :                       low = build_int_cst (ctype, r);
    3693              : 
    3694              :                       /* If there's only a lower bound, set the high bound
    3695              :                          to the maximum value of the case expression.  */
    3696           98 :                       if (!cp->high)
    3697            0 :                         high = TYPE_MAX_VALUE (ctype);
    3698              :                     }
    3699              : 
    3700          108 :                   if (cp->high)
    3701              :                     {
    3702           98 :                       if (!cp->low
    3703           98 :                           || (cp->low->value.character.string[0]
    3704           98 :                               != cp->high->value.character.string[0]))
    3705              :                         {
    3706            2 :                           if (cp->high->value.character.length > 0)
    3707            2 :                             r = cp->high->value.character.string[0];
    3708              :                           else
    3709              :                             r = ' ';
    3710            2 :                           high = build_int_cst (ctype, r);
    3711              :                         }
    3712              : 
    3713              :                       /* Unbounded case.  */
    3714           98 :                       if (!cp->low)
    3715            0 :                         low = TYPE_MIN_VALUE (ctype);
    3716              :                     }
    3717              : 
    3718              :                   /* Build a label.  */
    3719          108 :                   label = gfc_build_label_decl (NULL_TREE);
    3720              : 
    3721              :                   /* Add this case label.
    3722              :                      Add parameter 'label', make it match GCC backend.  */
    3723          108 :                   tmp = build_case_label (low, high, label);
    3724          108 :                   gfc_add_expr_to_block (&body, tmp);
    3725              :                 }
    3726              : 
    3727              :               /* Add the statements for this case.  */
    3728           42 :               tmp = gfc_trans_code (c->next);
    3729           42 :               gfc_add_expr_to_block (&body, tmp);
    3730              : 
    3731              :               /* Break to the end of the construct.  */
    3732           42 :               tmp = build1_v (GOTO_EXPR, end_label);
    3733           42 :               gfc_add_expr_to_block (&body, tmp);
    3734              :             }
    3735              : 
    3736           32 :           tmp = gfc_string_to_single_character (expr1se.string_length,
    3737              :                                                 expr1se.expr,
    3738           16 :                                                 code->expr1->ts.kind);
    3739           16 :           case_num = gfc_create_var (ctype, "case_num");
    3740           16 :           gfc_add_modify (&block, case_num, tmp);
    3741              : 
    3742           16 :           gfc_add_block_to_block (&block, &expr1se.post);
    3743              : 
    3744           16 :           tmp = gfc_finish_block (&body);
    3745           16 :           tmp = fold_build2_loc (input_location, SWITCH_EXPR, NULL_TREE,
    3746              :                                  case_num, tmp);
    3747           16 :           gfc_add_expr_to_block (&block, tmp);
    3748              : 
    3749           16 :           tmp = build1_v (LABEL_EXPR, end_label);
    3750           16 :           gfc_add_expr_to_block (&block, tmp);
    3751              : 
    3752           16 :           return gfc_finish_block (&block);
    3753              :         }
    3754              :     }
    3755              : 
    3756           59 :   if (code->expr1->ts.kind == 1)
    3757              :     k = 0;
    3758            6 :   else if (code->expr1->ts.kind == 4)
    3759              :     k = 1;
    3760              :   else
    3761            0 :     gcc_unreachable ();
    3762              : 
    3763           59 :   if (select_struct[k] == NULL)
    3764              :     {
    3765           53 :       tree *chain = NULL;
    3766           53 :       select_struct[k] = make_node (RECORD_TYPE);
    3767              : 
    3768           53 :       if (code->expr1->ts.kind == 1)
    3769           47 :         TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char1");
    3770            6 :       else if (code->expr1->ts.kind == 4)
    3771            6 :         TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char4");
    3772              :       else
    3773            0 :         gcc_unreachable ();
    3774              : 
    3775              : #undef ADD_FIELD
    3776              : #define ADD_FIELD(NAME, TYPE)                                               \
    3777              :   ss_##NAME[k] = gfc_add_field_to_struct (select_struct[k],                 \
    3778              :                                           get_identifier (stringize(NAME)), \
    3779              :                                           TYPE,                             \
    3780              :                                           &chain)
    3781              : 
    3782           53 :       ADD_FIELD (string1, pchartype);
    3783           53 :       ADD_FIELD (string1_len, gfc_charlen_type_node);
    3784              : 
    3785           53 :       ADD_FIELD (string2, pchartype);
    3786           53 :       ADD_FIELD (string2_len, gfc_charlen_type_node);
    3787              : 
    3788           53 :       ADD_FIELD (target, integer_type_node);
    3789              : #undef ADD_FIELD
    3790              : 
    3791           53 :       gfc_finish_type (select_struct[k]);
    3792              :     }
    3793              : 
    3794              :   n = 0;
    3795          311 :   for (d = cp; d; d = d->right)
    3796          252 :     d->n = n++;
    3797              : 
    3798          263 :   for (c = code->block; c; c = c->block)
    3799              :     {
    3800          456 :       for (d = c->ext.block.case_list; d; d = d->next)
    3801              :         {
    3802          252 :           label = gfc_build_label_decl (NULL_TREE);
    3803          452 :           tmp = build_case_label ((d->low == NULL && d->high == NULL)
    3804              :                                   ? NULL
    3805          200 :                                   : build_int_cst (integer_type_node, d->n),
    3806              :                                   NULL, label);
    3807          252 :           gfc_add_expr_to_block (&body, tmp);
    3808              :         }
    3809              : 
    3810          204 :       tmp = gfc_trans_code (c->next);
    3811          204 :       gfc_add_expr_to_block (&body, tmp);
    3812              : 
    3813          204 :       tmp = build1_v (GOTO_EXPR, end_label);
    3814          204 :       gfc_add_expr_to_block (&body, tmp);
    3815              :     }
    3816              : 
    3817              :   /* Generate the structure describing the branches */
    3818          311 :   for (d = cp; d; d = d->right)
    3819              :     {
    3820          252 :       vec<constructor_elt, va_gc> *node = NULL;
    3821              : 
    3822          252 :       gfc_init_se (&se, NULL);
    3823              : 
    3824          252 :       if (d->low == NULL)
    3825              :         {
    3826           52 :           CONSTRUCTOR_APPEND_ELT (node, ss_string1[k], null_pointer_node);
    3827           52 :           CONSTRUCTOR_APPEND_ELT (node, ss_string1_len[k], build_zero_cst (gfc_charlen_type_node));
    3828              :         }
    3829              :       else
    3830              :         {
    3831          200 :           gfc_conv_expr_reference (&se, d->low);
    3832              : 
    3833          200 :           CONSTRUCTOR_APPEND_ELT (node, ss_string1[k], se.expr);
    3834          200 :           CONSTRUCTOR_APPEND_ELT (node, ss_string1_len[k], se.string_length);
    3835              :         }
    3836              : 
    3837          252 :       if (d->high == NULL)
    3838              :         {
    3839           52 :           CONSTRUCTOR_APPEND_ELT (node, ss_string2[k], null_pointer_node);
    3840           52 :           CONSTRUCTOR_APPEND_ELT (node, ss_string2_len[k], build_zero_cst (gfc_charlen_type_node));
    3841              :         }
    3842              :       else
    3843              :         {
    3844          200 :           gfc_init_se (&se, NULL);
    3845          200 :           gfc_conv_expr_reference (&se, d->high);
    3846              : 
    3847          200 :           CONSTRUCTOR_APPEND_ELT (node, ss_string2[k], se.expr);
    3848          200 :           CONSTRUCTOR_APPEND_ELT (node, ss_string2_len[k], se.string_length);
    3849              :         }
    3850              : 
    3851          252 :       CONSTRUCTOR_APPEND_ELT (node, ss_target[k],
    3852              :                               build_int_cst (integer_type_node, d->n));
    3853              : 
    3854          252 :       tmp = build_constructor (select_struct[k], node);
    3855          252 :       CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, tmp);
    3856              :     }
    3857              : 
    3858           59 :   type = build_array_type (select_struct[k],
    3859           59 :                            build_index_type (size_int (n-1)));
    3860              : 
    3861           59 :   init = build_constructor (type, inits);
    3862           59 :   TREE_CONSTANT (init) = 1;
    3863           59 :   TREE_STATIC (init) = 1;
    3864              :   /* Create a static variable to hold the jump table.  */
    3865           59 :   tmp = gfc_create_var (type, "jumptable");
    3866           59 :   TREE_CONSTANT (tmp) = 1;
    3867           59 :   TREE_STATIC (tmp) = 1;
    3868           59 :   TREE_READONLY (tmp) = 1;
    3869           59 :   DECL_INITIAL (tmp) = init;
    3870           59 :   init = tmp;
    3871              : 
    3872              :   /* Build the library call */
    3873           59 :   init = gfc_build_addr_expr (pvoid_type_node, init);
    3874              : 
    3875           59 :   if (code->expr1->ts.kind == 1)
    3876           53 :     fndecl = gfor_fndecl_select_string;
    3877            6 :   else if (code->expr1->ts.kind == 4)
    3878            6 :     fndecl = gfor_fndecl_select_string_char4;
    3879              :   else
    3880            0 :     gcc_unreachable ();
    3881              : 
    3882           59 :   tmp = build_call_expr_loc (input_location,
    3883              :                          fndecl, 4, init,
    3884           59 :                          build_int_cst (gfc_charlen_type_node, n),
    3885              :                          expr1se.expr, expr1se.string_length);
    3886           59 :   case_num = gfc_create_var (integer_type_node, "case_num");
    3887           59 :   gfc_add_modify (&block, case_num, tmp);
    3888              : 
    3889           59 :   gfc_add_block_to_block (&block, &expr1se.post);
    3890              : 
    3891           59 :   tmp = gfc_finish_block (&body);
    3892           59 :   tmp = fold_build2_loc (input_location, SWITCH_EXPR, NULL_TREE,
    3893              :                          case_num, tmp);
    3894           59 :   gfc_add_expr_to_block (&block, tmp);
    3895              : 
    3896           59 :   tmp = build1_v (LABEL_EXPR, end_label);
    3897           59 :   gfc_add_expr_to_block (&block, tmp);
    3898              : 
    3899           59 :   return gfc_finish_block (&block);
    3900              : }
    3901              : 
    3902              : 
    3903              : /* Translate the three variants of the SELECT CASE construct.
    3904              : 
    3905              :    SELECT CASEs with INTEGER case expressions can be translated to an
    3906              :    equivalent GENERIC switch statement, and for LOGICAL case
    3907              :    expressions we build one or two if-else compares.
    3908              : 
    3909              :    SELECT CASEs with CHARACTER case expressions are a whole different
    3910              :    story, because they don't exist in GENERIC.  So we sort them and
    3911              :    do a binary search at runtime.
    3912              : 
    3913              :    Fortran has no BREAK statement, and it does not allow jumps from
    3914              :    one case block to another.  That makes things a lot easier for
    3915              :    the optimizers.  */
    3916              : 
    3917              : tree
    3918         1065 : gfc_trans_select (gfc_code * code)
    3919              : {
    3920         1065 :   stmtblock_t block;
    3921         1065 :   tree body;
    3922         1065 :   tree exit_label;
    3923              : 
    3924         1065 :   gcc_assert (code && code->expr1);
    3925         1065 :   gfc_init_block (&block);
    3926              : 
    3927              :   /* Build the exit label and hang it in.  */
    3928         1065 :   exit_label = gfc_build_label_decl (NULL_TREE);
    3929         1065 :   code->exit_label = exit_label;
    3930              : 
    3931              :   /* Empty SELECT constructs are legal.  */
    3932         1065 :   if (code->block == NULL)
    3933            2 :     body = build_empty_stmt (input_location);
    3934              : 
    3935              :   /* Select the correct translation function.  */
    3936              :   else
    3937         1063 :     switch (code->expr1->ts.type)
    3938              :       {
    3939           54 :       case BT_LOGICAL:
    3940           54 :         body = gfc_trans_logical_select (code);
    3941           54 :         break;
    3942              : 
    3943          934 :       case BT_INTEGER:
    3944          934 :       case BT_UNSIGNED:
    3945          934 :         body = gfc_trans_integer_select (code);
    3946          934 :         break;
    3947              : 
    3948           75 :       case BT_CHARACTER:
    3949           75 :         body = gfc_trans_character_select (code);
    3950           75 :         break;
    3951              : 
    3952            0 :       default:
    3953            0 :         gfc_internal_error ("gfc_trans_select(): Bad type for case expr.");
    3954              :         /* Not reached */
    3955              :       }
    3956              : 
    3957              :   /* Build everything together.  */
    3958         1065 :   gfc_add_expr_to_block (&block, body);
    3959         1065 :   gfc_add_expr_to_block (&block, build1_v (LABEL_EXPR, exit_label));
    3960              : 
    3961         1065 :   return gfc_finish_block (&block);
    3962              : }
    3963              : 
    3964              : tree
    3965         2922 : gfc_trans_select_type (gfc_code * code)
    3966              : {
    3967         2922 :   stmtblock_t block;
    3968         2922 :   tree body;
    3969         2922 :   tree exit_label;
    3970              : 
    3971         2922 :   gcc_assert (code && code->expr1);
    3972         2922 :   gfc_init_block (&block);
    3973              : 
    3974              :   /* Build the exit label and hang it in.  */
    3975         2922 :   exit_label = gfc_build_label_decl (NULL_TREE);
    3976         2922 :   code->exit_label = exit_label;
    3977              : 
    3978              :   /* Empty SELECT constructs are legal.  */
    3979         2922 :   if (code->block == NULL)
    3980            0 :     body = build_empty_stmt (input_location);
    3981              :   else
    3982         2922 :     body = gfc_trans_select_type_cases (code);
    3983              : 
    3984              :   /* Build everything together.  */
    3985         2922 :   gfc_add_expr_to_block (&block, body);
    3986              : 
    3987         2922 :   if (TREE_USED (exit_label))
    3988         2721 :     gfc_add_expr_to_block (&block, build1_v (LABEL_EXPR, exit_label));
    3989              : 
    3990         2922 :   return gfc_finish_block (&block);
    3991              : }
    3992              : 
    3993              : 
    3994              : static tree
    3995         1000 : gfc_trans_select_rank_cases (gfc_code * code)
    3996              : {
    3997         1000 :   gfc_code *c;
    3998         1000 :   gfc_case *cp;
    3999         1000 :   tree tmp;
    4000         1000 :   tree cond;
    4001         1000 :   tree low;
    4002         1000 :   tree rank;
    4003         1000 :   gfc_se se;
    4004         1000 :   gfc_se cse;
    4005         1000 :   stmtblock_t block;
    4006         1000 :   stmtblock_t body;
    4007         1000 :   bool def = false;
    4008              : 
    4009         1000 :   gfc_start_block (&block);
    4010              : 
    4011              :   /* Calculate the switch expression.  */
    4012         1000 :   gfc_init_se (&se, NULL);
    4013         1000 :   gfc_conv_expr_descriptor (&se, code->expr1);
    4014         1000 :   rank = gfc_conv_descriptor_rank (se.expr);
    4015         1000 :   rank = gfc_evaluate_now (rank, &block);
    4016         1000 :   symbol_attribute attr = gfc_expr_attr (code->expr1);
    4017         1000 :   if (!attr.pointer && !attr.allocatable)
    4018              :     {
    4019              :       /* Special case for assumed-rank ('rank(*)', internally -1):
    4020              :          rank = (rank == 0 || ubound[rank-1] != -1) ? rank : -1.  */
    4021          766 :       cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
    4022          766 :                               rank, build_int_cst (TREE_TYPE (rank), 0));
    4023          766 :       tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
    4024              :                              fold_convert (gfc_array_index_type, rank),
    4025              :                              gfc_index_one_node);
    4026          766 :       tmp = gfc_conv_descriptor_ubound_get (se.expr, tmp);
    4027          766 :       tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
    4028          766 :                              tmp, build_int_cst (TREE_TYPE (tmp), -1));
    4029          766 :       cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
    4030              :                               logical_type_node, cond, tmp);
    4031          766 :       tmp = fold_build3_loc (input_location, COND_EXPR, TREE_TYPE (rank),
    4032          766 :                              cond, rank, build_int_cst (TREE_TYPE (rank), -1));
    4033          766 :       rank = gfc_evaluate_now (tmp, &block);
    4034              :     }
    4035         1000 :   TREE_USED (code->exit_label) = 0;
    4036              : 
    4037         2000 : repeat:
    4038         6554 :   for (c = code->block; c; c = c->block)
    4039              :     {
    4040         4554 :       cp = c->ext.block.case_list;
    4041              : 
    4042              :       /* Assume it's the default case.  */
    4043         4554 :       low = NULL_TREE;
    4044         4554 :       tmp = NULL_TREE;
    4045              : 
    4046              :       /* Put the default case at the end.  */
    4047         4554 :       if ((!def && !cp->low) || (def && cp->low))
    4048         2277 :         continue;
    4049              : 
    4050         2277 :       if (cp->low)
    4051              :         {
    4052         1362 :           gfc_init_se (&cse, NULL);
    4053         1362 :           gfc_conv_expr_val (&cse, cp->low);
    4054         1362 :           gfc_add_block_to_block (&block, &cse.pre);
    4055         1362 :           low = cse.expr;
    4056              :         }
    4057              : 
    4058         2277 :       gfc_init_block (&body);
    4059              : 
    4060              :       /* Add the statements for this case.  */
    4061         2277 :       tmp = gfc_trans_code (c->next);
    4062         2277 :       gfc_add_expr_to_block (&body, tmp);
    4063              : 
    4064              :       /* Break to the end of the SELECT RANK construct.  The default
    4065              :          case just falls through.  */
    4066         2277 :       if (!def)
    4067              :         {
    4068         1362 :           TREE_USED (code->exit_label) = 1;
    4069         1362 :           tmp = build1_v (GOTO_EXPR, code->exit_label);
    4070         1362 :           gfc_add_expr_to_block (&body, tmp);
    4071              :         }
    4072              : 
    4073         2277 :       tmp = gfc_finish_block (&body);
    4074              : 
    4075         2277 :       if (low != NULL_TREE)
    4076              :         {
    4077         2724 :           cond = fold_build2_loc (input_location, EQ_EXPR,
    4078         1362 :                                   TREE_TYPE (rank), rank,
    4079         1362 :                                   fold_convert (TREE_TYPE (rank), low));
    4080         1362 :           tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
    4081              :                                  cond, tmp,
    4082              :                                  build_empty_stmt (input_location));
    4083              :         }
    4084              : 
    4085         2277 :       gfc_add_expr_to_block (&block, tmp);
    4086              :     }
    4087              : 
    4088         2000 :   if (!def)
    4089              :     {
    4090         1000 :       def = true;
    4091         1000 :       goto repeat;
    4092              :     }
    4093              : 
    4094         1000 :   return gfc_finish_block (&block);
    4095              : }
    4096              : 
    4097              : 
    4098              : tree
    4099         1001 : gfc_trans_select_rank (gfc_code * code)
    4100              : {
    4101         1001 :   stmtblock_t block;
    4102         1001 :   tree body;
    4103         1001 :   tree exit_label;
    4104              : 
    4105         1001 :   gcc_assert (code && code->expr1);
    4106         1001 :   gfc_init_block (&block);
    4107              : 
    4108              :   /* Build the exit label and hang it in.  */
    4109         1001 :   exit_label = gfc_build_label_decl (NULL_TREE);
    4110         1001 :   code->exit_label = exit_label;
    4111              : 
    4112              :   /* Empty SELECT constructs are legal.  */
    4113         1001 :   if (code->block == NULL)
    4114            1 :     body = build_empty_stmt (input_location);
    4115              :   else
    4116         1000 :     body = gfc_trans_select_rank_cases (code);
    4117              : 
    4118              :   /* Build everything together.  */
    4119         1001 :   gfc_add_expr_to_block (&block, body);
    4120              : 
    4121         1001 :   if (TREE_USED (exit_label))
    4122         1001 :     gfc_add_expr_to_block (&block, build1_v (LABEL_EXPR, exit_label));
    4123              : 
    4124         1001 :   return gfc_finish_block (&block);
    4125              : }
    4126              : 
    4127              : 
    4128              : /* Traversal function to substitute a replacement symtree if the symbol
    4129              :    in the expression is the same as that passed.  f == 2 signals that
    4130              :    that variable itself is not to be checked - only the references.
    4131              :    This group of functions is used when the variable expression in a
    4132              :    FORALL assignment has internal references.  For example:
    4133              :                 FORALL (i = 1:4) p(p(i)) = i
    4134              :    The only recourse here is to store a copy of 'p' for the index
    4135              :    expression.  */
    4136              : 
    4137              : static gfc_symtree *new_symtree;
    4138              : static gfc_symtree *old_symtree;
    4139              : 
    4140              : static bool
    4141          710 : forall_replace (gfc_expr *expr, gfc_symbol *sym, int *f)
    4142              : {
    4143          710 :   if (expr->expr_type != EXPR_VARIABLE)
    4144              :     return false;
    4145              : 
    4146          406 :   if (*f == 2)
    4147           62 :     *f = 1;
    4148          344 :   else if (expr->symtree->n.sym == sym)
    4149           72 :     expr->symtree = new_symtree;
    4150              : 
    4151              :   return false;
    4152              : }
    4153              : 
    4154              : static void
    4155          124 : forall_replace_symtree (gfc_expr *e, gfc_symbol *sym, int f)
    4156              : {
    4157            0 :   gfc_traverse_expr (e, sym, forall_replace, f);
    4158            0 : }
    4159              : 
    4160              : static bool
    4161          710 : forall_restore (gfc_expr *expr,
    4162              :                 gfc_symbol *sym ATTRIBUTE_UNUSED,
    4163              :                 int *f ATTRIBUTE_UNUSED)
    4164              : {
    4165          710 :   if (expr->expr_type != EXPR_VARIABLE)
    4166              :     return false;
    4167              : 
    4168          406 :   if (expr->symtree == new_symtree)
    4169           72 :     expr->symtree = old_symtree;
    4170              : 
    4171              :   return false;
    4172              : }
    4173              : 
    4174              : static void
    4175          124 : forall_restore_symtree (gfc_expr *e)
    4176              : {
    4177            0 :   gfc_traverse_expr (e, NULL, forall_restore, 0);
    4178            0 : }
    4179              : 
    4180              : static void
    4181           62 : forall_make_variable_temp (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
    4182              : {
    4183           62 :   gfc_se tse;
    4184           62 :   gfc_se rse;
    4185           62 :   gfc_expr *e;
    4186           62 :   gfc_symbol *new_sym;
    4187           62 :   gfc_symbol *old_sym;
    4188           62 :   gfc_symtree *root;
    4189           62 :   tree tmp;
    4190              : 
    4191              :   /* Build a copy of the lvalue.  */
    4192           62 :   old_symtree = c->expr1->symtree;
    4193           62 :   old_sym = old_symtree->n.sym;
    4194           62 :   e = gfc_lval_expr_from_sym (old_sym);
    4195           62 :   if (old_sym->attr.dimension)
    4196              :     {
    4197           30 :       gfc_init_se (&tse, NULL);
    4198           30 :       gfc_conv_subref_array_arg (&tse, e, 0, INTENT_IN, false);
    4199           30 :       gfc_add_block_to_block (pre, &tse.pre);
    4200           30 :       gfc_add_block_to_block (post, &tse.post);
    4201           30 :       tse.expr = build_fold_indirect_ref_loc (input_location, tse.expr);
    4202              : 
    4203           30 :       if (c->expr1->ref->u.ar.type != AR_SECTION)
    4204              :         {
    4205              :           /* Use the variable offset for the temporary.  */
    4206           24 :           tmp = gfc_conv_array_offset (old_sym->backend_decl);
    4207           24 :           gfc_conv_descriptor_offset_set (pre, tse.expr, tmp);
    4208              :         }
    4209              :     }
    4210              :   else
    4211              :     {
    4212           32 :       gfc_init_se (&tse, NULL);
    4213           32 :       gfc_init_se (&rse, NULL);
    4214           32 :       gfc_conv_expr (&rse, e);
    4215           32 :       if (e->ts.type == BT_CHARACTER)
    4216              :         {
    4217           32 :           tse.string_length = rse.string_length;
    4218           32 :           tmp = gfc_get_character_type_len (gfc_default_character_kind,
    4219              :                                             tse.string_length);
    4220           32 :           tse.expr = gfc_conv_string_tmp (&tse, build_pointer_type (tmp),
    4221              :                                           rse.string_length);
    4222           32 :           gfc_add_block_to_block (pre, &tse.pre);
    4223           32 :           gfc_add_block_to_block (post, &tse.post);
    4224              :         }
    4225              :       else
    4226              :         {
    4227            0 :           tmp = gfc_typenode_for_spec (&e->ts);
    4228            0 :           tse.expr = gfc_create_var (tmp, "temp");
    4229              :         }
    4230              : 
    4231           64 :       tmp = gfc_trans_scalar_assign (&tse, &rse, e->ts,
    4232           32 :                                      e->expr_type == EXPR_VARIABLE, false);
    4233           32 :       gfc_add_expr_to_block (pre, tmp);
    4234              :     }
    4235           62 :   gfc_free_expr (e);
    4236              : 
    4237              :   /* Create a new symbol to represent the lvalue.  */
    4238           62 :   new_sym = gfc_new_symbol (old_sym->name, NULL);
    4239           62 :   new_sym->ts = old_sym->ts;
    4240           62 :   new_sym->attr.referenced = 1;
    4241           62 :   new_sym->attr.temporary = 1;
    4242           62 :   new_sym->attr.dimension = old_sym->attr.dimension;
    4243           62 :   new_sym->attr.flavor = old_sym->attr.flavor;
    4244              : 
    4245              :   /* Use the temporary as the backend_decl.  */
    4246           62 :   new_sym->backend_decl = tse.expr;
    4247              : 
    4248              :   /* Create a fake symtree for it.  */
    4249           62 :   root = NULL;
    4250           62 :   new_symtree = gfc_new_symtree (&root, old_sym->name);
    4251           62 :   new_symtree->n.sym = new_sym;
    4252           62 :   gcc_assert (new_symtree == root);
    4253              : 
    4254              :   /* Go through the expression reference replacing the old_symtree
    4255              :      with the new.  */
    4256           62 :   forall_replace_symtree (c->expr1, old_sym, 2);
    4257              : 
    4258              :   /* Now we have made this temporary, we might as well use it for
    4259              :   the right hand side.  */
    4260           62 :   forall_replace_symtree (c->expr2, old_sym, 1);
    4261           62 : }
    4262              : 
    4263              : 
    4264              : /* Handles dependencies in forall assignments.  */
    4265              : static int
    4266         1826 : check_forall_dependencies (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
    4267              : {
    4268         1826 :   gfc_ref *lref;
    4269         1826 :   gfc_ref *rref;
    4270         1826 :   int need_temp;
    4271         1826 :   gfc_symbol *lsym;
    4272              : 
    4273         1826 :   lsym = c->expr1->symtree->n.sym;
    4274         1826 :   need_temp = gfc_check_dependency (c->expr1, c->expr2, 0);
    4275              : 
    4276              :   /* Now check for dependencies within the 'variable'
    4277              :      expression itself.  These are treated by making a complete
    4278              :      copy of variable and changing all the references to it
    4279              :      point to the copy instead.  Note that the shallow copy of
    4280              :      the variable will not suffice for derived types with
    4281              :      pointer components.  We therefore leave these to their
    4282              :      own devices.  Likewise for allocatable components.  */
    4283         1826 :   if (lsym->ts.type == BT_DERIVED
    4284          149 :       && (lsym->ts.u.derived->attr.pointer_comp
    4285          139 :           || lsym->ts.u.derived->attr.alloc_comp))
    4286              :     return need_temp;
    4287              : 
    4288         1731 :   new_symtree = NULL;
    4289         1731 :   if (find_forall_index (c->expr1, lsym, 2))
    4290              :     {
    4291           12 :       forall_make_variable_temp (c, pre, post);
    4292           12 :       need_temp = 0;
    4293              :     }
    4294              : 
    4295              :   /* Substrings with dependencies are treated in the same
    4296              :      way.  */
    4297         1731 :   if (c->expr1->ts.type == BT_CHARACTER
    4298          685 :         && c->expr1->ref
    4299          685 :         && c->expr2->expr_type == EXPR_VARIABLE
    4300          492 :         && lsym == c->expr2->symtree->n.sym)
    4301              :     {
    4302          124 :       for (lref = c->expr1->ref; lref; lref = lref->next)
    4303          117 :         if (lref->type == REF_SUBSTRING)
    4304              :           break;
    4305          124 :       for (rref = c->expr2->ref; rref; rref = rref->next)
    4306          117 :         if (rref->type == REF_SUBSTRING)
    4307              :           break;
    4308              : 
    4309           81 :       if (rref && lref
    4310           81 :             && gfc_dep_compare_expr (rref->u.ss.start, lref->u.ss.start) < 0)
    4311              :         {
    4312           50 :           forall_make_variable_temp (c, pre, post);
    4313           50 :           need_temp = 0;
    4314              :         }
    4315              :     }
    4316              :   return need_temp;
    4317              : }
    4318              : 
    4319              : 
    4320              : static void
    4321           62 : cleanup_forall_symtrees (gfc_code *c)
    4322              : {
    4323           62 :   forall_restore_symtree (c->expr1);
    4324           62 :   forall_restore_symtree (c->expr2);
    4325           62 :   free (new_symtree->n.sym);
    4326           62 :   free (new_symtree);
    4327           62 : }
    4328              : 
    4329              : 
    4330              : /* Generate the loops for a FORALL block, specified by FORALL_TMP.  BODY
    4331              :    is the contents of the FORALL block/stmt to be iterated.  MASK_FLAG
    4332              :    indicates whether we should generate code to test the FORALLs mask
    4333              :    array.  OUTER is the loop header to be used for initializing mask
    4334              :    indices.
    4335              : 
    4336              :    The generated loop format is:
    4337              :     count = (end - start + step) / step
    4338              :     loopvar = start
    4339              :     while (1)
    4340              :       {
    4341              :         if (count <=0 )
    4342              :           goto end_of_loop
    4343              :         <body>
    4344              :         loopvar += step
    4345              :         count --
    4346              :       }
    4347              :     end_of_loop:  */
    4348              : 
    4349              : static tree
    4350         3533 : gfc_trans_forall_loop (forall_info *forall_tmp, tree body,
    4351              :                        int mask_flag, stmtblock_t *outer)
    4352              : {
    4353         3533 :   int n, nvar;
    4354         3533 :   tree tmp;
    4355         3533 :   tree cond;
    4356         3533 :   stmtblock_t block;
    4357         3533 :   tree exit_label;
    4358         3533 :   tree count;
    4359         3533 :   tree var, start, end, step;
    4360         3533 :   iter_info *iter;
    4361              : 
    4362              :   /* Initialize the mask index outside the FORALL nest.  */
    4363         3533 :   if (mask_flag && forall_tmp->mask)
    4364         1071 :     gfc_add_modify (outer, forall_tmp->maskindex, gfc_index_zero_node);
    4365              : 
    4366         3533 :   iter = forall_tmp->this_loop;
    4367         3533 :   nvar = forall_tmp->nvar;
    4368         9745 :   for (n = 0; n < nvar; n++)
    4369              :     {
    4370         6212 :       var = iter->var;
    4371         6212 :       start = iter->start;
    4372         6212 :       end = iter->end;
    4373         6212 :       step = iter->step;
    4374              : 
    4375         6212 :       exit_label = gfc_build_label_decl (NULL_TREE);
    4376         6212 :       TREE_USED (exit_label) = 1;
    4377              : 
    4378              :       /* The loop counter.  */
    4379         6212 :       count = gfc_create_var (TREE_TYPE (var), "count");
    4380              : 
    4381              :       /* The body of the loop.  */
    4382         6212 :       gfc_init_block (&block);
    4383              : 
    4384              :       /* The exit condition.  */
    4385         6212 :       cond = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
    4386         6212 :                               count, build_int_cst (TREE_TYPE (count), 0));
    4387              : 
    4388              :       /* PR 83064 means that we cannot use annot_expr_parallel_kind until
    4389              :        the autoparallelizer can handle this.  */
    4390         6212 :       if (forall_tmp->do_concurrent || iter->annot.ivdep)
    4391          165 :         cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
    4392              :                        build_int_cst (integer_type_node,
    4393              :                                       annot_expr_ivdep_kind),
    4394              :                        integer_zero_node);
    4395              : 
    4396         6212 :       if (iter->annot.unroll && cond != error_mark_node)
    4397            1 :         cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
    4398              :                        build_int_cst (integer_type_node,
    4399              :                                       annot_expr_unroll_kind),
    4400            1 :                        build_int_cst (integer_type_node, iter->annot.unroll));
    4401              : 
    4402         6212 :       if (iter->annot.vector && cond != error_mark_node)
    4403            1 :         cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
    4404              :                        build_int_cst (integer_type_node,
    4405              :                                       annot_expr_vector_kind),
    4406              :                        integer_zero_node);
    4407              : 
    4408         6212 :       if (iter->annot.novector && cond != error_mark_node)
    4409            2 :         cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
    4410              :                        build_int_cst (integer_type_node,
    4411              :                                       annot_expr_no_vector_kind),
    4412              :                        integer_zero_node);
    4413              : 
    4414         6212 :       tmp = build1_v (GOTO_EXPR, exit_label);
    4415         6212 :       tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
    4416              :                              cond, tmp, build_empty_stmt (input_location));
    4417         6212 :       gfc_add_expr_to_block (&block, tmp);
    4418              : 
    4419              :       /* The main loop body.  */
    4420         6212 :       gfc_add_expr_to_block (&block, body);
    4421              : 
    4422              :       /* Increment the loop variable.  */
    4423         6212 :       tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), var,
    4424              :                              step);
    4425         6212 :       gfc_add_modify (&block, var, tmp);
    4426              : 
    4427              :       /* Advance to the next mask element.  Only do this for the
    4428              :          innermost loop.  */
    4429         6212 :       if (n == 0 && mask_flag && forall_tmp->mask)
    4430              :         {
    4431         1071 :           tree maskindex = forall_tmp->maskindex;
    4432         1071 :           tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
    4433              :                                  maskindex, gfc_index_one_node);
    4434         1071 :           gfc_add_modify (&block, maskindex, tmp);
    4435              :         }
    4436              : 
    4437              :       /* Decrement the loop counter.  */
    4438         6212 :       tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (var), count,
    4439         6212 :                              build_int_cst (TREE_TYPE (var), 1));
    4440         6212 :       gfc_add_modify (&block, count, tmp);
    4441              : 
    4442         6212 :       body = gfc_finish_block (&block);
    4443              : 
    4444              :       /* Loop var initialization.  */
    4445         6212 :       gfc_init_block (&block);
    4446         6212 :       gfc_add_modify (&block, var, start);
    4447              : 
    4448              : 
    4449              :       /* Initialize the loop counter.  */
    4450         6212 :       tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (var), step,
    4451              :                              start);
    4452         6212 :       tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), end,
    4453              :                              tmp);
    4454         6212 :       tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, TREE_TYPE (var),
    4455              :                              tmp, step);
    4456         6212 :       gfc_add_modify (&block, count, tmp);
    4457              : 
    4458              :       /* The loop expression.  */
    4459         6212 :       tmp = build1_v (LOOP_EXPR, body);
    4460         6212 :       gfc_add_expr_to_block (&block, tmp);
    4461              : 
    4462              :       /* The exit label.  */
    4463         6212 :       tmp = build1_v (LABEL_EXPR, exit_label);
    4464         6212 :       gfc_add_expr_to_block (&block, tmp);
    4465              : 
    4466         6212 :       body = gfc_finish_block (&block);
    4467         6212 :       iter = iter->next;
    4468              :     }
    4469         3533 :   return body;
    4470              : }
    4471              : 
    4472              : 
    4473              : /* Generate the body and loops according to MASK_FLAG.  If MASK_FLAG
    4474              :    is nonzero, the body is controlled by all masks in the forall nest.
    4475              :    Otherwise, the innermost loop is not controlled by it's mask.  This
    4476              :    is used for initializing that mask.  */
    4477              : 
    4478              : static tree
    4479         3333 : gfc_trans_nested_forall_loop (forall_info * nested_forall_info, tree body,
    4480              :                               int mask_flag)
    4481              : {
    4482         3333 :   tree tmp;
    4483         3333 :   stmtblock_t header;
    4484         3333 :   forall_info *forall_tmp;
    4485         3333 :   tree mask, maskindex;
    4486              : 
    4487         3333 :   gfc_start_block (&header);
    4488              : 
    4489         3333 :   forall_tmp = nested_forall_info;
    4490        10199 :   while (forall_tmp != NULL)
    4491              :     {
    4492              :       /* Generate body with masks' control.  */
    4493         3533 :       if (mask_flag)
    4494              :         {
    4495         2808 :           mask = forall_tmp->mask;
    4496         2808 :           maskindex = forall_tmp->maskindex;
    4497              : 
    4498              :           /* If a mask was specified make the assignment conditional.  */
    4499         2808 :           if (mask)
    4500              :             {
    4501         1071 :               tmp = gfc_build_array_ref (mask, maskindex, NULL);
    4502         1071 :               body = build3_v (COND_EXPR, tmp, body,
    4503              :                                build_empty_stmt (input_location));
    4504              :             }
    4505              :         }
    4506         3533 :       body = gfc_trans_forall_loop (forall_tmp, body, mask_flag, &header);
    4507         3533 :       forall_tmp = forall_tmp->prev_nest;
    4508         3533 :       mask_flag = 1;
    4509              :     }
    4510              : 
    4511         3333 :   gfc_add_expr_to_block (&header, body);
    4512         3333 :   return gfc_finish_block (&header);
    4513              : }
    4514              : 
    4515              : 
    4516              : /* Allocate data for holding a temporary array.  Returns either a local
    4517              :    temporary array or a pointer variable.  */
    4518              : 
    4519              : static tree
    4520         1384 : gfc_do_allocate (tree bytesize, tree size, tree * pdata, stmtblock_t * pblock,
    4521              :                  tree elem_type)
    4522              : {
    4523         1384 :   tree tmpvar;
    4524         1384 :   tree type;
    4525         1384 :   tree tmp;
    4526              : 
    4527         1384 :   if (INTEGER_CST_P (size))
    4528         1140 :     tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
    4529              :                            size, gfc_index_one_node);
    4530              :   else
    4531              :     tmp = NULL_TREE;
    4532              : 
    4533         1384 :   type = build_range_type (gfc_array_index_type, gfc_index_zero_node, tmp);
    4534         1384 :   type = build_array_type (elem_type, type);
    4535         1384 :   if (gfc_can_put_var_on_stack (bytesize) && INTEGER_CST_P (size))
    4536              :     {
    4537         1140 :       tmpvar = gfc_create_var (type, "temp");
    4538         1140 :       *pdata = NULL_TREE;
    4539              :     }
    4540              :   else
    4541              :     {
    4542          244 :       tmpvar = gfc_create_var (build_pointer_type (type), "temp");
    4543          244 :       *pdata = convert (pvoid_type_node, tmpvar);
    4544              : 
    4545          244 :       tmp = gfc_call_malloc (pblock, TREE_TYPE (tmpvar), bytesize);
    4546          244 :       gfc_add_modify (pblock, tmpvar, tmp);
    4547              :     }
    4548         1384 :   return tmpvar;
    4549              : }
    4550              : 
    4551              : 
    4552              : /* Generate codes to copy the temporary to the actual lhs.  */
    4553              : 
    4554              : static tree
    4555          224 : generate_loop_for_temp_to_lhs (gfc_expr *expr, tree tmp1, tree count3,
    4556              :                                tree count1,
    4557              :                                gfc_ss *lss, gfc_ss *rss,
    4558              :                                tree wheremask, bool invert)
    4559              : {
    4560          224 :   stmtblock_t block, body1;
    4561          224 :   gfc_loopinfo loop;
    4562          224 :   gfc_se lse;
    4563          224 :   gfc_se rse;
    4564          224 :   tree tmp;
    4565          224 :   tree wheremaskexpr;
    4566              : 
    4567          224 :   (void) rss; /* TODO: unused.  */
    4568              : 
    4569          224 :   gfc_start_block (&block);
    4570              : 
    4571          224 :   gfc_init_se (&rse, NULL);
    4572          224 :   gfc_init_se (&lse, NULL);
    4573              : 
    4574          224 :   if (lss == gfc_ss_terminator)
    4575              :     {
    4576          149 :       gfc_init_block (&body1);
    4577          149 :       gfc_conv_expr (&lse, expr);
    4578          149 :       rse.expr = gfc_build_array_ref (tmp1, count1, NULL);
    4579              :     }
    4580              :   else
    4581              :     {
    4582              :       /* Initialize the loop.  */
    4583           75 :       gfc_init_loopinfo (&loop);
    4584              : 
    4585              :       /* We may need LSS to determine the shape of the expression.  */
    4586           75 :       gfc_add_ss_to_loop (&loop, lss);
    4587              : 
    4588           75 :       gfc_conv_ss_startstride (&loop);
    4589           75 :       gfc_conv_loop_setup (&loop, &expr->where);
    4590              : 
    4591           75 :       gfc_mark_ss_chain_used (lss, 1);
    4592              :       /* Start the loop body.  */
    4593           75 :       gfc_start_scalarized_body (&loop, &body1);
    4594              : 
    4595              :       /* Translate the expression.  */
    4596           75 :       gfc_copy_loopinfo_to_se (&lse, &loop);
    4597           75 :       lse.ss = lss;
    4598           75 :       gfc_conv_expr (&lse, expr);
    4599              : 
    4600              :       /* Form the expression of the temporary.  */
    4601           75 :       rse.expr = gfc_build_array_ref (tmp1, count1, NULL);
    4602              :     }
    4603              : 
    4604              :   /* Use the scalar assignment.  */
    4605          224 :   rse.string_length = lse.string_length;
    4606          448 :   tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts,
    4607          224 :                                  expr->expr_type == EXPR_VARIABLE, false);
    4608              : 
    4609              :   /* Form the mask expression according to the mask tree list.  */
    4610          224 :   if (wheremask)
    4611              :     {
    4612           27 :       wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
    4613           27 :       if (invert)
    4614            0 :         wheremaskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
    4615            0 :                                          TREE_TYPE (wheremaskexpr),
    4616              :                                          wheremaskexpr);
    4617           27 :       tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
    4618              :                              wheremaskexpr, tmp,
    4619              :                              build_empty_stmt (input_location));
    4620              :     }
    4621              : 
    4622          224 :   gfc_add_expr_to_block (&body1, tmp);
    4623              : 
    4624          224 :   tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (count1),
    4625              :                          count1, gfc_index_one_node);
    4626          224 :   gfc_add_modify (&body1, count1, tmp);
    4627              : 
    4628          224 :   if (lss == gfc_ss_terminator)
    4629          149 :       gfc_add_block_to_block (&block, &body1);
    4630              :   else
    4631              :     {
    4632              :       /* Increment count3.  */
    4633           75 :       if (count3)
    4634              :         {
    4635           27 :           tmp = fold_build2_loc (input_location, PLUS_EXPR,
    4636              :                                  gfc_array_index_type,
    4637              :                                  count3, gfc_index_one_node);
    4638           27 :           gfc_add_modify (&body1, count3, tmp);
    4639              :         }
    4640              : 
    4641              :       /* Generate the copying loops.  */
    4642           75 :       gfc_trans_scalarizing_loops (&loop, &body1);
    4643              : 
    4644           75 :       gfc_add_block_to_block (&block, &loop.pre);
    4645           75 :       gfc_add_block_to_block (&block, &loop.post);
    4646              : 
    4647           75 :       gfc_cleanup_loop (&loop);
    4648              :       /* TODO: Reuse lss and rss when copying temp->lhs.  Need to be careful
    4649              :          as tree nodes in SS may not be valid in different scope.  */
    4650              :     }
    4651              : 
    4652          224 :   tmp = gfc_finish_block (&block);
    4653          224 :   return tmp;
    4654              : }
    4655              : 
    4656              : 
    4657              : /* Generate codes to copy rhs to the temporary. TMP1 is the address of
    4658              :    temporary, LSS and RSS are formed in function compute_inner_temp_size(),
    4659              :    and should not be freed.  WHEREMASK is the conditional execution mask
    4660              :    whose sense may be inverted by INVERT.  */
    4661              : 
    4662              : static tree
    4663          224 : generate_loop_for_rhs_to_temp (gfc_expr *expr2, tree tmp1, tree count3,
    4664              :                                tree count1, gfc_ss *lss, gfc_ss *rss,
    4665              :                                tree wheremask, bool invert)
    4666              : {
    4667          224 :   stmtblock_t block, body1;
    4668          224 :   gfc_loopinfo loop;
    4669          224 :   gfc_se lse;
    4670          224 :   gfc_se rse;
    4671          224 :   tree tmp;
    4672          224 :   tree wheremaskexpr;
    4673              : 
    4674          224 :   gfc_start_block (&block);
    4675              : 
    4676          224 :   gfc_init_se (&rse, NULL);
    4677          224 :   gfc_init_se (&lse, NULL);
    4678              : 
    4679          224 :   if (lss == gfc_ss_terminator)
    4680              :     {
    4681          149 :       gfc_init_block (&body1);
    4682          149 :       gfc_conv_expr (&rse, expr2);
    4683          149 :       lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
    4684              :     }
    4685              :   else
    4686              :     {
    4687              :       /* Initialize the loop.  */
    4688           75 :       gfc_init_loopinfo (&loop);
    4689              : 
    4690              :       /* We may need LSS to determine the shape of the expression.  */
    4691           75 :       gfc_add_ss_to_loop (&loop, lss);
    4692           75 :       gfc_add_ss_to_loop (&loop, rss);
    4693              : 
    4694           75 :       gfc_conv_ss_startstride (&loop);
    4695           75 :       gfc_conv_loop_setup (&loop, &expr2->where);
    4696              : 
    4697           75 :       gfc_mark_ss_chain_used (rss, 1);
    4698              :       /* Start the loop body.  */
    4699           75 :       gfc_start_scalarized_body (&loop, &body1);
    4700              : 
    4701              :       /* Translate the expression.  */
    4702           75 :       gfc_copy_loopinfo_to_se (&rse, &loop);
    4703           75 :       rse.ss = rss;
    4704           75 :       gfc_conv_expr (&rse, expr2);
    4705              : 
    4706              :       /* Form the expression of the temporary.  */
    4707           75 :       lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
    4708              :     }
    4709              : 
    4710              :   /* Use the scalar assignment.  */
    4711          224 :   lse.string_length = rse.string_length;
    4712          448 :   tmp = gfc_trans_scalar_assign (&lse, &rse, expr2->ts,
    4713          224 :                                  expr2->expr_type == EXPR_VARIABLE, false);
    4714              : 
    4715              :   /* Form the mask expression according to the mask tree list.  */
    4716          224 :   if (wheremask)
    4717              :     {
    4718           27 :       wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
    4719           27 :       if (invert)
    4720            0 :         wheremaskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
    4721            0 :                                          TREE_TYPE (wheremaskexpr),
    4722              :                                          wheremaskexpr);
    4723           27 :       tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
    4724              :                              wheremaskexpr, tmp,
    4725              :                              build_empty_stmt (input_location));
    4726              :     }
    4727              : 
    4728          224 :   gfc_add_expr_to_block (&body1, tmp);
    4729              : 
    4730          224 :   if (lss == gfc_ss_terminator)
    4731              :     {
    4732          149 :       gfc_add_block_to_block (&block, &body1);
    4733              : 
    4734              :       /* Increment count1.  */
    4735          149 :       tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (count1),
    4736              :                              count1, gfc_index_one_node);
    4737          149 :       gfc_add_modify (&block, count1, tmp);
    4738              :     }
    4739              :   else
    4740              :     {
    4741              :       /* Increment count1.  */
    4742           75 :       tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
    4743              :                              count1, gfc_index_one_node);
    4744           75 :       gfc_add_modify (&body1, count1, tmp);
    4745              : 
    4746              :       /* Increment count3.  */
    4747           75 :       if (count3)
    4748              :         {
    4749           27 :           tmp = fold_build2_loc (input_location, PLUS_EXPR,
    4750              :                                  gfc_array_index_type,
    4751              :                                  count3, gfc_index_one_node);
    4752           27 :           gfc_add_modify (&body1, count3, tmp);
    4753              :         }
    4754              : 
    4755              :       /* Generate the copying loops.  */
    4756           75 :       gfc_trans_scalarizing_loops (&loop, &body1);
    4757              : 
    4758           75 :       gfc_add_block_to_block (&block, &loop.pre);
    4759           75 :       gfc_add_block_to_block (&block, &loop.post);
    4760              : 
    4761           75 :       gfc_cleanup_loop (&loop);
    4762              :       /* TODO: Reuse lss and rss when copying temp->lhs.  Need to be careful
    4763              :          as tree nodes in SS may not be valid in different scope.  */
    4764              :     }
    4765              : 
    4766          224 :   tmp = gfc_finish_block (&block);
    4767          224 :   return tmp;
    4768              : }
    4769              : 
    4770              : 
    4771              : /* Calculate the size of temporary needed in the assignment inside forall.
    4772              :    LSS and RSS are filled in this function.  */
    4773              : 
    4774              : static tree
    4775          780 : compute_inner_temp_size (gfc_expr *expr1, gfc_expr *expr2,
    4776              :                          stmtblock_t * pblock,
    4777              :                          gfc_ss **lss, gfc_ss **rss)
    4778              : {
    4779          780 :   gfc_loopinfo loop;
    4780          780 :   tree size;
    4781          780 :   int i;
    4782          780 :   int save_flag;
    4783          780 :   tree tmp;
    4784              : 
    4785          780 :   *lss = gfc_walk_expr (expr1);
    4786          780 :   *rss = NULL;
    4787              : 
    4788          780 :   size = gfc_index_one_node;
    4789          780 :   if (*lss != gfc_ss_terminator)
    4790              :     {
    4791          482 :       gfc_init_loopinfo (&loop);
    4792              : 
    4793              :       /* Walk the RHS of the expression.  */
    4794          482 :       *rss = gfc_walk_expr (expr2);
    4795          482 :       if (*rss == gfc_ss_terminator)
    4796              :         /* The rhs is scalar.  Add a ss for the expression.  */
    4797            0 :         *rss = gfc_get_scalar_ss (gfc_ss_terminator, expr2);
    4798              : 
    4799              :       /* Associate the SS with the loop.  */
    4800          482 :       gfc_add_ss_to_loop (&loop, *lss);
    4801              :       /* We don't actually need to add the rhs at this point, but it might
    4802              :          make guessing the loop bounds a bit easier.  */
    4803          482 :       gfc_add_ss_to_loop (&loop, *rss);
    4804              : 
    4805              :       /* We only want the shape of the expression, not rest of the junk
    4806              :          generated by the scalarizer.  */
    4807          482 :       loop.array_parameter = 1;
    4808              : 
    4809              :       /* Calculate the bounds of the scalarization.  */
    4810          482 :       save_flag = gfc_option.rtcheck;
    4811          482 :       gfc_option.rtcheck &= ~GFC_RTCHECK_BOUNDS;
    4812          482 :       gfc_conv_ss_startstride (&loop);
    4813          482 :       gfc_option.rtcheck = save_flag;
    4814          482 :       gfc_conv_loop_setup (&loop, &expr2->where);
    4815              : 
    4816              :       /* Figure out how many elements we need.  */
    4817         1477 :       for (i = 0; i < loop.dimen; i++)
    4818              :         {
    4819          513 :           tmp = fold_build2_loc (input_location, MINUS_EXPR,
    4820              :                                  gfc_array_index_type,
    4821              :                                  gfc_index_one_node, loop.from[i]);
    4822          513 :           tmp = fold_build2_loc (input_location, PLUS_EXPR,
    4823              :                                  gfc_array_index_type, tmp, loop.to[i]);
    4824          513 :           size = fold_build2_loc (input_location, MULT_EXPR,
    4825              :                                   gfc_array_index_type, size, tmp);
    4826              :         }
    4827          482 :       gfc_add_block_to_block (pblock, &loop.pre);
    4828          482 :       size = gfc_evaluate_now (size, pblock);
    4829          482 :       gfc_add_block_to_block (pblock, &loop.post);
    4830              : 
    4831              :       /* TODO: write a function that cleans up a loopinfo without freeing
    4832              :          the SS chains.  Currently a NOP.  */
    4833              :     }
    4834              : 
    4835          780 :   return size;
    4836              : }
    4837              : 
    4838              : 
    4839              : /* Calculate the overall iterator number of the nested forall construct.
    4840              :    This routine actually calculates the number of times the body of the
    4841              :    nested forall specified by NESTED_FORALL_INFO is executed and multiplies
    4842              :    that by the expression INNER_SIZE.  The BLOCK argument specifies the
    4843              :    block in which to calculate the result, and the optional INNER_SIZE_BODY
    4844              :    argument contains any statements that need to executed (inside the loop)
    4845              :    to initialize or calculate INNER_SIZE.  */
    4846              : 
    4847              : static tree
    4848         1301 : compute_overall_iter_number (forall_info *nested_forall_info, tree inner_size,
    4849              :                              stmtblock_t *inner_size_body, stmtblock_t *block)
    4850              : {
    4851         1301 :   forall_info *forall_tmp = nested_forall_info;
    4852         1301 :   tree tmp, number;
    4853         1301 :   stmtblock_t body;
    4854              : 
    4855              :   /* We can eliminate the innermost unconditional loops with constant
    4856              :      array bounds.  */
    4857         1301 :   if (INTEGER_CST_P (inner_size))
    4858              :     {
    4859              :       while (forall_tmp
    4860          268 :              && !forall_tmp->mask
    4861         1508 :              && INTEGER_CST_P (forall_tmp->size))
    4862              :         {
    4863          117 :           inner_size = fold_build2_loc (input_location, MULT_EXPR,
    4864              :                                         gfc_array_index_type,
    4865              :                                         inner_size, forall_tmp->size);
    4866          117 :           forall_tmp = forall_tmp->prev_nest;
    4867              :         }
    4868              : 
    4869              :       /* If there are no loops left, we have our constant result.  */
    4870         1209 :       if (!forall_tmp)
    4871              :         return inner_size;
    4872              :     }
    4873              : 
    4874              :   /* Otherwise, create a temporary variable to compute the result.  */
    4875          243 :   number = gfc_create_var (gfc_array_index_type, "num");
    4876          243 :   gfc_add_modify (block, number, gfc_index_zero_node);
    4877              : 
    4878          243 :   gfc_start_block (&body);
    4879          243 :   if (inner_size_body)
    4880          189 :     gfc_add_block_to_block (&body, inner_size_body);
    4881          243 :   if (forall_tmp)
    4882          226 :     tmp = fold_build2_loc (input_location, PLUS_EXPR,
    4883              :                            gfc_array_index_type, number, inner_size);
    4884              :   else
    4885              :     tmp = inner_size;
    4886          243 :   gfc_add_modify (&body, number, tmp);
    4887          243 :   tmp = gfc_finish_block (&body);
    4888              : 
    4889              :   /* Generate loops.  */
    4890          243 :   if (forall_tmp != NULL)
    4891          226 :     tmp = gfc_trans_nested_forall_loop (forall_tmp, tmp, 1);
    4892              : 
    4893          243 :   gfc_add_expr_to_block (block, tmp);
    4894              : 
    4895          243 :   return number;
    4896              : }
    4897              : 
    4898              : 
    4899              : /* Allocate temporary for forall construct.  SIZE is the size of temporary
    4900              :    needed.  PTEMP1 is returned for space free.  */
    4901              : 
    4902              : static tree
    4903         1384 : allocate_temp_for_forall_nest_1 (tree type, tree size, stmtblock_t * block,
    4904              :                                  tree * ptemp1)
    4905              : {
    4906         1384 :   tree bytesize;
    4907         1384 :   tree unit;
    4908         1384 :   tree tmp;
    4909              : 
    4910         1384 :   unit = fold_convert (gfc_array_index_type, TYPE_SIZE_UNIT (type));
    4911         1384 :   if (!integer_onep (unit))
    4912          166 :     bytesize = fold_build2_loc (input_location, MULT_EXPR,
    4913              :                                 gfc_array_index_type, size, unit);
    4914              :   else
    4915              :     bytesize = size;
    4916              : 
    4917         1384 :   *ptemp1 = NULL;
    4918         1384 :   tmp = gfc_do_allocate (bytesize, size, ptemp1, block, type);
    4919              : 
    4920         1384 :   if (*ptemp1)
    4921          244 :     tmp = build_fold_indirect_ref_loc (input_location, tmp);
    4922         1384 :   return tmp;
    4923              : }
    4924              : 
    4925              : 
    4926              : /* Allocate temporary for forall construct according to the information in
    4927              :    nested_forall_info.  INNER_SIZE is the size of temporary needed in the
    4928              :    assignment inside forall.  PTEMP1 is returned for space free.  */
    4929              : 
    4930              : static tree
    4931          969 : allocate_temp_for_forall_nest (forall_info * nested_forall_info, tree type,
    4932              :                                tree inner_size, stmtblock_t * inner_size_body,
    4933              :                                stmtblock_t * block, tree * ptemp1)
    4934              : {
    4935          969 :   tree size;
    4936              : 
    4937              :   /* Calculate the total size of temporary needed in forall construct.  */
    4938          969 :   size = compute_overall_iter_number (nested_forall_info, inner_size,
    4939              :                                       inner_size_body, block);
    4940              : 
    4941          969 :   return allocate_temp_for_forall_nest_1 (type, size, block, ptemp1);
    4942              : }
    4943              : 
    4944              : 
    4945              : /* Handle assignments inside forall which need temporary.
    4946              : 
    4947              :     forall (i=start:end:stride; maskexpr)
    4948              :       e<i> = f<i>
    4949              :     end forall
    4950              :    (where e,f<i> are arbitrary expressions possibly involving i
    4951              :     and there is a dependency between e<i> and f<i>)
    4952              :    Translates to:
    4953              :     masktmp(:) = maskexpr(:)
    4954              : 
    4955              :     maskindex = 0;
    4956              :     count1 = 0;
    4957              :     num = 0;
    4958              :     for (i = start; i <= end; i += stride)
    4959              :       num += SIZE (f<i>)
    4960              :     count1 = 0;
    4961              :     ALLOCATE (tmp(num))
    4962              :     for (i = start; i <= end; i += stride)
    4963              :       {
    4964              :         if (masktmp[maskindex++])
    4965              :           tmp[count1++] = f<i>
    4966              :       }
    4967              :     maskindex = 0;
    4968              :     count1 = 0;
    4969              :     for (i = start; i <= end; i += stride)
    4970              :       {
    4971              :         if (masktmp[maskindex++])
    4972              :           e<i> = tmp[count1++]
    4973              :       }
    4974              :     DEALLOCATE (tmp)
    4975              :   */
    4976              : static void
    4977          224 : gfc_trans_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
    4978              :                             tree wheremask, bool invert,
    4979              :                             forall_info * nested_forall_info,
    4980              :                             stmtblock_t * block)
    4981              : {
    4982          224 :   tree type;
    4983          224 :   tree inner_size;
    4984          224 :   gfc_ss *lss, *rss;
    4985          224 :   tree count, count1;
    4986          224 :   tree tmp, tmp1;
    4987          224 :   tree ptemp1;
    4988          224 :   stmtblock_t inner_size_body;
    4989              : 
    4990              :   /* Create vars. count1 is the current iterator number of the nested
    4991              :      forall.  */
    4992          224 :   count1 = gfc_create_var (gfc_array_index_type, "count1");
    4993              : 
    4994              :   /* Count is the wheremask index.  */
    4995          224 :   if (wheremask)
    4996              :     {
    4997           27 :       count = gfc_create_var (gfc_array_index_type, "count");
    4998           27 :       gfc_add_modify (block, count, gfc_index_zero_node);
    4999              :     }
    5000              :   else
    5001              :     count = NULL;
    5002              : 
    5003              :   /* Initialize count1.  */
    5004          224 :   gfc_add_modify (block, count1, gfc_index_zero_node);
    5005              : 
    5006              :   /* Calculate the size of temporary needed in the assignment. Return loop, lss
    5007              :      and rss which are used in function generate_loop_for_rhs_to_temp().  */
    5008              :   /* The type of LHS. Used in function allocate_temp_for_forall_nest */
    5009          224 :   if (expr1->ts.type == BT_CHARACTER)
    5010              :     {
    5011          103 :       type = NULL;
    5012          103 :       if (expr1->ref && expr1->ref->type == REF_SUBSTRING)
    5013              :         {
    5014           72 :           gfc_se ssse;
    5015           72 :           gfc_init_se (&ssse, NULL);
    5016           72 :           gfc_conv_expr (&ssse, expr1);
    5017           72 :           type = gfc_get_character_type_len (gfc_default_character_kind,
    5018              :                                              ssse.string_length);
    5019           72 :         }
    5020              :       else
    5021              :         {
    5022           31 :           if (!expr1->ts.u.cl->backend_decl)
    5023              :             {
    5024            6 :               gfc_se tse;
    5025            6 :               gcc_assert (expr1->ts.u.cl->length);
    5026            6 :               gfc_init_se (&tse, NULL);
    5027            6 :               gfc_conv_expr (&tse, expr1->ts.u.cl->length);
    5028            6 :               expr1->ts.u.cl->backend_decl = tse.expr;
    5029              :             }
    5030           31 :           type = gfc_get_character_type_len (gfc_default_character_kind,
    5031           31 :                                              expr1->ts.u.cl->backend_decl);
    5032              :         }
    5033              :     }
    5034              :   else
    5035          121 :     type = gfc_typenode_for_spec (&expr1->ts);
    5036              : 
    5037          224 :   gfc_init_block (&inner_size_body);
    5038          224 :   inner_size = compute_inner_temp_size (expr1, expr2, &inner_size_body,
    5039              :                                         &lss, &rss);
    5040              : 
    5041              :   /* Allocate temporary for nested forall construct according to the
    5042              :      information in nested_forall_info and inner_size.  */
    5043          224 :   tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type, inner_size,
    5044              :                                         &inner_size_body, block, &ptemp1);
    5045              : 
    5046              :   /* Generate codes to copy rhs to the temporary .  */
    5047          224 :   tmp = generate_loop_for_rhs_to_temp (expr2, tmp1, count, count1, lss, rss,
    5048              :                                        wheremask, invert);
    5049              : 
    5050              :   /* Generate body and loops according to the information in
    5051              :      nested_forall_info.  */
    5052          224 :   tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
    5053          224 :   gfc_add_expr_to_block (block, tmp);
    5054              : 
    5055              :   /* Reset count1.  */
    5056          224 :   gfc_add_modify (block, count1, gfc_index_zero_node);
    5057              : 
    5058              :   /* Reset count.  */
    5059          224 :   if (wheremask)
    5060           27 :     gfc_add_modify (block, count, gfc_index_zero_node);
    5061              : 
    5062              :   /* TODO: Second call to compute_inner_temp_size to initialize lss and
    5063              :      rss;  there must be a better way.  */
    5064          224 :   inner_size = compute_inner_temp_size (expr1, expr2, &inner_size_body,
    5065              :                                         &lss, &rss);
    5066              : 
    5067              :   /* Generate codes to copy the temporary to lhs.  */
    5068          224 :   tmp = generate_loop_for_temp_to_lhs (expr1, tmp1, count, count1,
    5069              :                                        lss, rss,
    5070              :                                        wheremask, invert);
    5071              : 
    5072              :   /* Generate body and loops according to the information in
    5073              :      nested_forall_info.  */
    5074          224 :   tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
    5075          224 :   gfc_add_expr_to_block (block, tmp);
    5076              : 
    5077          224 :   if (ptemp1)
    5078              :     {
    5079              :       /* Free the temporary.  */
    5080          145 :       tmp = gfc_call_free (ptemp1);
    5081          145 :       gfc_add_expr_to_block (block, tmp);
    5082              :     }
    5083          224 : }
    5084              : 
    5085              : 
    5086              : /* Translate pointer assignment inside FORALL which need temporary.  */
    5087              : 
    5088              : static void
    5089           20 : gfc_trans_pointer_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
    5090              :                                     forall_info * nested_forall_info,
    5091              :                                     stmtblock_t * block)
    5092              : {
    5093           20 :   tree type;
    5094           20 :   tree inner_size;
    5095           20 :   gfc_ss *lss, *rss;
    5096           20 :   gfc_se lse;
    5097           20 :   gfc_se rse;
    5098           20 :   gfc_array_info *info;
    5099           20 :   gfc_loopinfo loop;
    5100           20 :   tree desc;
    5101           20 :   tree parm;
    5102           20 :   tree parmtype;
    5103           20 :   stmtblock_t body;
    5104           20 :   tree count;
    5105           20 :   tree tmp, tmp1, ptemp1;
    5106              : 
    5107           20 :   count = gfc_create_var (gfc_array_index_type, "count");
    5108           20 :   gfc_add_modify (block, count, gfc_index_zero_node);
    5109              : 
    5110           20 :   inner_size = gfc_index_one_node;
    5111           20 :   lss = gfc_walk_expr (expr1);
    5112           20 :   rss = gfc_walk_expr (expr2);
    5113           20 :   if (lss == gfc_ss_terminator)
    5114              :     {
    5115           11 :       type = gfc_typenode_for_spec (&expr1->ts);
    5116           11 :       type = build_pointer_type (type);
    5117              : 
    5118              :       /* Allocate temporary for nested forall construct according to the
    5119              :          information in nested_forall_info and inner_size.  */
    5120           11 :       tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type,
    5121              :                                             inner_size, NULL, block, &ptemp1);
    5122           11 :       gfc_start_block (&body);
    5123           11 :       gfc_init_se (&lse, NULL);
    5124           11 :       lse.expr = gfc_build_array_ref (tmp1, count, NULL);
    5125           11 :       gfc_init_se (&rse, NULL);
    5126           11 :       rse.want_pointer = 1;
    5127           11 :       gfc_conv_expr (&rse, expr2);
    5128           11 :       gfc_add_block_to_block (&body, &rse.pre);
    5129           11 :       gfc_add_modify (&body, lse.expr,
    5130           11 :                            fold_convert (TREE_TYPE (lse.expr), rse.expr));
    5131           11 :       gfc_add_block_to_block (&body, &rse.post);
    5132              : 
    5133              :       /* Increment count.  */
    5134           11 :       tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
    5135              :                              count, gfc_index_one_node);
    5136           11 :       gfc_add_modify (&body, count, tmp);
    5137              : 
    5138           11 :       tmp = gfc_finish_block (&body);
    5139              : 
    5140              :       /* Generate body and loops according to the information in
    5141              :          nested_forall_info.  */
    5142           11 :       tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
    5143           11 :       gfc_add_expr_to_block (block, tmp);
    5144              : 
    5145              :       /* Reset count.  */
    5146           11 :       gfc_add_modify (block, count, gfc_index_zero_node);
    5147              : 
    5148           11 :       gfc_start_block (&body);
    5149           11 :       gfc_init_se (&lse, NULL);
    5150           11 :       gfc_init_se (&rse, NULL);
    5151           11 :       rse.expr = gfc_build_array_ref (tmp1, count, NULL);
    5152           11 :       lse.want_pointer = 1;
    5153           11 :       gfc_conv_expr (&lse, expr1);
    5154           11 :       gfc_add_block_to_block (&body, &lse.pre);
    5155           11 :       gfc_add_modify (&body, lse.expr, rse.expr);
    5156           11 :       gfc_add_block_to_block (&body, &lse.post);
    5157              :       /* Increment count.  */
    5158           11 :       tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
    5159              :                              count, gfc_index_one_node);
    5160           11 :       gfc_add_modify (&body, count, tmp);
    5161           11 :       tmp = gfc_finish_block (&body);
    5162              : 
    5163              :       /* Generate body and loops according to the information in
    5164              :          nested_forall_info.  */
    5165           11 :       tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
    5166           11 :       gfc_add_expr_to_block (block, tmp);
    5167              :     }
    5168              :   else
    5169              :     {
    5170            9 :       gfc_init_loopinfo (&loop);
    5171              : 
    5172              :       /* Associate the SS with the loop.  */
    5173            9 :       gfc_add_ss_to_loop (&loop, rss);
    5174              : 
    5175              :       /* Setup the scalarizing loops and bounds.  */
    5176            9 :       gfc_conv_ss_startstride (&loop);
    5177              : 
    5178            9 :       gfc_conv_loop_setup (&loop, &expr2->where);
    5179              : 
    5180            9 :       info = &rss->info->data.array;
    5181            9 :       desc = info->descriptor;
    5182              : 
    5183              :       /* Make a new descriptor.  */
    5184            9 :       parmtype = gfc_get_element_type (TREE_TYPE (desc));
    5185            9 :       parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen, 0,
    5186              :                                             loop.from, loop.to, 1,
    5187              :                                             GFC_ARRAY_UNKNOWN, true);
    5188              : 
    5189              :       /* Allocate temporary for nested forall construct.  */
    5190            9 :       tmp1 = allocate_temp_for_forall_nest (nested_forall_info, parmtype,
    5191              :                                             inner_size, NULL, block, &ptemp1);
    5192            9 :       gfc_start_block (&body);
    5193            9 :       gfc_init_se (&lse, NULL);
    5194            9 :       lse.expr = gfc_build_array_ref (tmp1, count, NULL);
    5195            9 :       lse.direct_byref = 1;
    5196            9 :       gfc_conv_expr_descriptor (&lse, expr2);
    5197              : 
    5198            9 :       gfc_add_block_to_block (&body, &lse.pre);
    5199            9 :       gfc_add_block_to_block (&body, &lse.post);
    5200              : 
    5201              :       /* Increment count.  */
    5202            9 :       tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
    5203              :                              count, gfc_index_one_node);
    5204            9 :       gfc_add_modify (&body, count, tmp);
    5205              : 
    5206            9 :       tmp = gfc_finish_block (&body);
    5207              : 
    5208              :       /* Generate body and loops according to the information in
    5209              :          nested_forall_info.  */
    5210            9 :       tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
    5211            9 :       gfc_add_expr_to_block (block, tmp);
    5212              : 
    5213              :       /* Reset count.  */
    5214            9 :       gfc_add_modify (block, count, gfc_index_zero_node);
    5215              : 
    5216            9 :       parm = gfc_build_array_ref (tmp1, count, NULL);
    5217            9 :       gfc_init_se (&lse, NULL);
    5218            9 :       gfc_conv_expr_descriptor (&lse, expr1);
    5219            9 :       gfc_add_modify (&lse.pre, lse.expr, parm);
    5220            9 :       gfc_start_block (&body);
    5221            9 :       gfc_add_block_to_block (&body, &lse.pre);
    5222            9 :       gfc_add_block_to_block (&body, &lse.post);
    5223              : 
    5224              :       /* Increment count.  */
    5225            9 :       tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
    5226              :                              count, gfc_index_one_node);
    5227            9 :       gfc_add_modify (&body, count, tmp);
    5228              : 
    5229            9 :       tmp = gfc_finish_block (&body);
    5230              : 
    5231            9 :       tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
    5232            9 :       gfc_add_expr_to_block (block, tmp);
    5233              :     }
    5234              :   /* Free the temporary.  */
    5235           20 :   if (ptemp1)
    5236              :     {
    5237            1 :       tmp = gfc_call_free (ptemp1);
    5238            1 :       gfc_add_expr_to_block (block, tmp);
    5239              :     }
    5240           20 : }
    5241              : 
    5242              : /* For saving the outer-variable data when doing
    5243              :    LOCAL and LOCAL_INIT substitution.  */
    5244              : struct symbol_and_tree_t
    5245              : {
    5246              :   gfc_symbol *sym;
    5247              :   gfc_expr *value;
    5248              :   tree decl;
    5249              :   symbol_attribute attr;
    5250              : };
    5251              : 
    5252              : /* Handle the LOCAL and LOCAL_INIT locality specifiers. This has to be
    5253              :    called twice, once with after_body=false - and then after the loop
    5254              :    body has been processed with after_body=true.
    5255              : 
    5256              :    Creates a copy of the variables that appear in the LOCAL and LOCAL_INIT
    5257              :    locality specifiers of 'do concurrent' - and use it in the original
    5258              :    gfc_symbol.  The declaration is then reset by after_body=true.
    5259              : 
    5260              :    Variables in LOCAL_INIT are set in every loop iteration.  */
    5261              : 
    5262              : void
    5263          296 : gfc_trans_concurrent_locality_spec (bool after_body, stmtblock_t *body,
    5264              :                                     std::vector<symbol_and_tree_t> *saved_decls,
    5265              :                                     gfc_expr_list **locality_list)
    5266              : {
    5267          296 :   if (!locality_list[LOCALITY_LOCAL] && !locality_list[LOCALITY_LOCAL_INIT])
    5268              :     return;
    5269              : 
    5270           96 :   if (after_body)
    5271              :     {
    5272          205 :       for (unsigned i = 0; i < saved_decls->size (); i++)
    5273              :         {
    5274          157 :           (*saved_decls)[i].sym->backend_decl = (*saved_decls)[i].decl;
    5275          157 :           (*saved_decls)[i].sym->attr = (*saved_decls)[i].attr;
    5276          157 :           (*saved_decls)[i].sym->value = (*saved_decls)[i].value;
    5277              :         }
    5278              :       return;
    5279              :     }
    5280              : 
    5281              :   gfc_expr_list *el;
    5282              :   int cnt = 0;
    5283          144 :   for (int i = 0; i <= 1; i++)
    5284           96 :     for (el = locality_list[i == 0 ? LOCALITY_LOCAL : LOCALITY_LOCAL_INIT];
    5285          253 :          el; el = el->next)
    5286              :       {
    5287          157 :         gfc_symbol *outer_sym = el->expr->symtree->n.sym;
    5288          157 :         if (!outer_sym->backend_decl)
    5289            0 :           outer_sym->backend_decl = gfc_get_symbol_decl (outer_sym);
    5290          157 :         cnt++;
    5291              :       }
    5292           48 :   saved_decls->resize (cnt);
    5293              : 
    5294              :   /* The variables have to be created in the scope of the loop body.  */
    5295           48 :   if (!body->has_scope)
    5296              :     {
    5297           48 :       gcc_checking_assert (body->head == NULL_TREE);
    5298           48 :       gfc_start_block (body);
    5299              :     }
    5300           48 :   gfc_start_saved_local_decls ();
    5301              : 
    5302           48 :   cnt = 0;
    5303           48 :   static_assert (LOCALITY_LOCAL_INIT - LOCALITY_LOCAL == 1, "locality_type");
    5304          144 :   for (int type = LOCALITY_LOCAL;
    5305          144 :        type <= LOCALITY_LOCAL_INIT; type++)
    5306          253 :     for (el = locality_list[type]; el; el = el->next)
    5307              :       {
    5308          157 :         gfc_symbol *sym = el->expr->symtree->n.sym;
    5309          157 :         (*saved_decls)[cnt].sym = sym;
    5310          157 :         (*saved_decls)[cnt].attr = sym->attr;
    5311          157 :         (*saved_decls)[cnt].value = sym->value;
    5312          157 :         (*saved_decls)[cnt].decl = sym->backend_decl;
    5313              : 
    5314          157 :         if (sym->attr.dimension && sym->as->type == AS_ASSUMED_SHAPE)
    5315              :           {
    5316            3 :             gfc_error ("Sorry, %s specifier at %L for assumed-size array %qs "
    5317              :                        "is not yet supported",
    5318              :                        type == LOCALITY_LOCAL ? "LOCAL" : "LOCAL_INIT",
    5319              :                        &el->expr->where, sym->name);
    5320            2 :             continue;
    5321              :           }
    5322              : 
    5323          155 :         gfc_symbol outer_sym = *sym;
    5324              : 
    5325              :         /* Create the inner local variable.  */
    5326          155 :         sym->backend_decl = NULL;
    5327          155 :         sym->value = NULL;
    5328          155 :         sym->attr.save = SAVE_NONE;
    5329          155 :         sym->attr.value = 0;
    5330          155 :         sym->attr.dummy = 0;
    5331          155 :         sym->attr.optional = 0;
    5332              : 
    5333          155 :         {
    5334              :           /* Slightly ugly hack for adding the decl via add_decl_as_local. */
    5335          155 :           gfc_symbol dummy_block_sym;
    5336          155 :           dummy_block_sym.attr.flavor = FL_LABEL;
    5337          155 :           gfc_symbol *saved_proc_name = sym->ns->proc_name;
    5338          155 :           sym->ns->proc_name = &dummy_block_sym;
    5339              : 
    5340          155 :           gfc_get_symbol_decl (sym);
    5341          310 :           DECL_SOURCE_LOCATION (sym->backend_decl)
    5342          155 :             = gfc_get_location (&el->expr->where);
    5343              : 
    5344          155 :           sym->ns->proc_name = saved_proc_name;
    5345              :         }
    5346              : 
    5347          155 :         symbol_attribute attr = gfc_expr_attr (el->expr);
    5348          155 :         if (type == LOCALITY_LOCAL
    5349           89 :             && !attr.pointer
    5350           41 :             && sym->ts.type == BT_DERIVED
    5351          183 :             && gfc_has_default_initializer (sym->ts.u.derived))
    5352              :           /* Cf. PR fortran/  */
    5353            4 :           gfc_error ("Sorry, LOCAL specifier at %L for %qs of derived type with"
    5354              :                      " default initializer is not yet supported",
    5355            4 :                      &el->expr->where, sym->name);
    5356          155 :         if (type == LOCALITY_LOCAL_INIT)
    5357              :           {
    5358              :             /* LOCAL_INIT:  local_var = outer_var.  */
    5359           66 :             gfc_symtree st = *el->expr->symtree;
    5360           66 :             st.n.sym = &outer_sym;
    5361           66 :             gfc_expr expr = *el->expr;
    5362           66 :             expr.symtree = &st;
    5363           66 :             tree t = (attr.pointer
    5364           66 :                       ? gfc_trans_pointer_assignment (el->expr, &expr)
    5365           42 :                       : gfc_trans_assignment (el->expr, &expr, false, false,
    5366              :                                               false, false));
    5367           66 :             gfc_add_expr_to_block (body, t);
    5368              :           }
    5369          155 :         cnt++;
    5370              :       }
    5371           48 :   gfc_stop_saved_local_decls ();
    5372              : }
    5373              : 
    5374              : 
    5375              : /* FORALL and WHERE statements are really nasty, especially when you nest
    5376              :    them. All the rhs of a forall assignment must be evaluated before the
    5377              :    actual assignments are performed. Presumably this also applies to all the
    5378              :    assignments in an inner where statement.  */
    5379              : 
    5380              : /* Generate code for a FORALL statement.  Any temporaries are allocated as a
    5381              :    linear array, relying on the fact that we process in the same order in all
    5382              :    loops.
    5383              : 
    5384              :     forall (i=start:end:stride; maskexpr)
    5385              :       e<i> = f<i>
    5386              :       g<i> = h<i>
    5387              :     end forall
    5388              :    (where e,f,g,h<i> are arbitrary expressions possibly involving i)
    5389              :    Translates to:
    5390              :     count = ((end + 1 - start) / stride)
    5391              :     masktmp(:) = maskexpr(:)
    5392              : 
    5393              :     maskindex = 0;
    5394              :     for (i = start; i <= end; i += stride)
    5395              :       {
    5396              :         if (masktmp[maskindex++])
    5397              :           e<i> = f<i>
    5398              :       }
    5399              :     maskindex = 0;
    5400              :     for (i = start; i <= end; i += stride)
    5401              :       {
    5402              :         if (masktmp[maskindex++])
    5403              :           g<i> = h<i>
    5404              :       }
    5405              : 
    5406              :     Note that this code only works when there are no dependencies.
    5407              :     Forall loop with array assignments and data dependencies are a real pain,
    5408              :     because the size of the temporary cannot always be determined before the
    5409              :     loop is executed.  This problem is compounded by the presence of nested
    5410              :     FORALL constructs.
    5411              :  */
    5412              : 
    5413              : static tree
    5414         2113 : gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info)
    5415              : {
    5416         2113 :   stmtblock_t pre;
    5417         2113 :   stmtblock_t post;
    5418         2113 :   stmtblock_t block;
    5419         2113 :   stmtblock_t body;
    5420         2113 :   tree *var;
    5421         2113 :   tree *start;
    5422         2113 :   tree *end;
    5423         2113 :   tree *step;
    5424         2113 :   gfc_expr **varexpr;
    5425         2113 :   tree tmp;
    5426         2113 :   tree assign;
    5427         2113 :   tree size;
    5428         2113 :   tree maskindex;
    5429         2113 :   tree mask;
    5430         2113 :   tree pmask;
    5431         2113 :   tree cycle_label = NULL_TREE;
    5432         2113 :   int n;
    5433         2113 :   int nvar;
    5434         2113 :   int need_temp;
    5435         2113 :   gfc_forall_iterator *fa;
    5436         2113 :   gfc_se se;
    5437         2113 :   gfc_code *c;
    5438         2113 :   gfc_saved_var *saved_vars;
    5439         2113 :   iter_info *this_forall;
    5440         2113 :   forall_info *info;
    5441         2113 :   bool need_mask;
    5442              : 
    5443              :   /* Do nothing if the mask is false.  */
    5444         2113 :   if (code->expr1
    5445          727 :       && code->expr1->expr_type == EXPR_CONSTANT
    5446            2 :       && !code->expr1->value.logical)
    5447            1 :     return build_empty_stmt (input_location);
    5448              : 
    5449         2112 :   n = 0;
    5450              :   /* Count the FORALL index number.  */
    5451         6135 :   for (fa = code->ext.concur.forall_iterator; fa; fa = fa->next)
    5452         4023 :     n++;
    5453         2112 :   nvar = n;
    5454              : 
    5455              :   /* Allocate the space for var, start, end, step, varexpr.  */
    5456         2112 :   var = XCNEWVEC (tree, nvar);
    5457         2112 :   start = XCNEWVEC (tree, nvar);
    5458         2112 :   end = XCNEWVEC (tree, nvar);
    5459         2112 :   step = XCNEWVEC (tree, nvar);
    5460         2112 :   varexpr = XCNEWVEC (gfc_expr *, nvar);
    5461         2112 :   saved_vars = XCNEWVEC (gfc_saved_var, nvar);
    5462              : 
    5463              :   /* Allocate the space for info.  */
    5464         2112 :   info = XCNEW (forall_info);
    5465              : 
    5466         2112 :   gfc_start_block (&pre);
    5467         2112 :   gfc_init_block (&post);
    5468         2112 :   gfc_init_block (&block);
    5469              : 
    5470         2112 :   n = 0;
    5471         6135 :   for (fa = code->ext.concur.forall_iterator; fa; fa = fa->next)
    5472              :     {
    5473         4023 :       gfc_symbol *sym = fa->var->symtree->n.sym;
    5474              : 
    5475              :       /* Allocate space for this_forall.  */
    5476         4023 :       this_forall = XCNEW (iter_info);
    5477              : 
    5478              :       /* Create a temporary variable for the FORALL index.  */
    5479         4023 :       tmp = gfc_typenode_for_spec (&sym->ts);
    5480         4023 :       var[n] = gfc_create_var (tmp, sym->name);
    5481         4023 :       gfc_shadow_sym (sym, var[n], &saved_vars[n]);
    5482              : 
    5483              :       /* Record it in this_forall.  */
    5484         4023 :       this_forall->var = var[n];
    5485              : 
    5486              :       /* Replace the index symbol's backend_decl with the temporary decl.  */
    5487         4023 :       sym->backend_decl = var[n];
    5488              : 
    5489              :       /* Work out the start, end and stride for the loop.  */
    5490         4023 :       gfc_init_se (&se, NULL);
    5491         4023 :       gfc_conv_expr_val (&se, fa->start);
    5492              :       /* Record it in this_forall.  */
    5493         4023 :       this_forall->start = se.expr;
    5494         4023 :       gfc_add_block_to_block (&block, &se.pre);
    5495         4023 :       start[n] = se.expr;
    5496              : 
    5497         4023 :       gfc_init_se (&se, NULL);
    5498         4023 :       gfc_conv_expr_val (&se, fa->end);
    5499              :       /* Record it in this_forall.  */
    5500         4023 :       this_forall->end = se.expr;
    5501         4023 :       gfc_make_safe_expr (&se);
    5502         4023 :       gfc_add_block_to_block (&block, &se.pre);
    5503         4023 :       end[n] = se.expr;
    5504              : 
    5505         4023 :       gfc_init_se (&se, NULL);
    5506         4023 :       gfc_conv_expr_val (&se, fa->stride);
    5507              :       /* Record it in this_forall.  */
    5508         4023 :       this_forall->step = se.expr;
    5509         4023 :       gfc_make_safe_expr (&se);
    5510         4023 :       gfc_add_block_to_block (&block, &se.pre);
    5511         4023 :       step[n] = se.expr;
    5512              : 
    5513              :       /* Copy loop annotations.  */
    5514         4023 :       this_forall->annot = fa->annot;
    5515              : 
    5516              :       /* Set the NEXT field of this_forall to NULL.  */
    5517         4023 :       this_forall->next = NULL;
    5518              :       /* Link this_forall to the info construct.  */
    5519         4023 :       if (info->this_loop)
    5520              :         {
    5521              :           iter_info *iter_tmp = info->this_loop;
    5522         2837 :           while (iter_tmp->next != NULL)
    5523              :             iter_tmp = iter_tmp->next;
    5524         1911 :           iter_tmp->next = this_forall;
    5525              :         }
    5526              :       else
    5527         2112 :         info->this_loop = this_forall;
    5528              : 
    5529         4023 :       n++;
    5530              :     }
    5531         2112 :   nvar = n;
    5532              : 
    5533              :   /* Calculate the size needed for the current forall level.  */
    5534         2112 :   size = gfc_index_one_node;
    5535         6135 :   for (n = 0; n < nvar; n++)
    5536              :     {
    5537              :       /* size = (end + step - start) / step.  */
    5538         4023 :       tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (start[n]),
    5539         4023 :                              step[n], start[n]);
    5540         4023 :       tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (end[n]),
    5541         4023 :                              end[n], tmp);
    5542         4023 :       tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR, TREE_TYPE (tmp),
    5543              :                              tmp, step[n]);
    5544         4023 :       tmp = convert (gfc_array_index_type, tmp);
    5545              : 
    5546         4023 :       size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
    5547              :                               size, tmp);
    5548              :     }
    5549              : 
    5550              :   /* Record the nvar and size of current forall level.  */
    5551         2112 :   info->nvar = nvar;
    5552         2112 :   info->size = size;
    5553              : 
    5554         2112 :   if (code->expr1)
    5555              :     {
    5556              :       /* If the mask is .true., consider the FORALL unconditional.  */
    5557          726 :       if (code->expr1->expr_type == EXPR_CONSTANT
    5558            1 :           && code->expr1->value.logical)
    5559              :         need_mask = false;
    5560              :       else
    5561          725 :         need_mask = true;
    5562              :     }
    5563              :   else
    5564              :     need_mask = false;
    5565              : 
    5566              :   /* First we need to allocate the mask.  */
    5567          725 :   if (need_mask)
    5568              :     {
    5569              :       /* As the mask array can be very big, prefer compact boolean types.  */
    5570          725 :       tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
    5571          725 :       mask = allocate_temp_for_forall_nest (nested_forall_info, mask_type,
    5572              :                                             size, NULL, &block, &pmask);
    5573          725 :       maskindex = gfc_create_var_np (gfc_array_index_type, "mi");
    5574              : 
    5575              :       /* Record them in the info structure.  */
    5576          725 :       info->maskindex = maskindex;
    5577          725 :       info->mask = mask;
    5578              :     }
    5579              :   else
    5580              :     {
    5581              :       /* No mask was specified.  */
    5582         1387 :       maskindex = NULL_TREE;
    5583         1387 :       mask = pmask = NULL_TREE;
    5584              :     }
    5585              : 
    5586              :   /* Link the current forall level to nested_forall_info.  */
    5587         2112 :   info->prev_nest = nested_forall_info;
    5588         2112 :   nested_forall_info = info;
    5589              : 
    5590              :   /* Copy the mask into a temporary variable if required.
    5591              :      For now we assume a mask temporary is needed.  */
    5592         2112 :   if (need_mask)
    5593              :     {
    5594              :       /* As the mask array can be very big, prefer compact boolean types.  */
    5595          725 :       tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
    5596              : 
    5597          725 :       gfc_add_modify (&block, maskindex, gfc_index_zero_node);
    5598              : 
    5599              :       /* Start of mask assignment loop body.  */
    5600          725 :       gfc_start_block (&body);
    5601              : 
    5602              :       /* Evaluate the mask expression.  */
    5603          725 :       gfc_init_se (&se, NULL);
    5604          725 :       gfc_conv_expr_val (&se, code->expr1);
    5605          725 :       gfc_add_block_to_block (&body, &se.pre);
    5606              : 
    5607              :       /* Store the mask.  */
    5608          725 :       se.expr = convert (mask_type, se.expr);
    5609              : 
    5610          725 :       tmp = gfc_build_array_ref (mask, maskindex, NULL);
    5611          725 :       gfc_add_modify (&body, tmp, se.expr);
    5612              : 
    5613              :       /* Advance to the next mask element.  */
    5614          725 :       tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
    5615              :                              maskindex, gfc_index_one_node);
    5616          725 :       gfc_add_modify (&body, maskindex, tmp);
    5617              : 
    5618              :       /* Generate the loops.  */
    5619          725 :       tmp = gfc_finish_block (&body);
    5620          725 :       tmp = gfc_trans_nested_forall_loop (info, tmp, 0);
    5621          725 :       gfc_add_expr_to_block (&block, tmp);
    5622              :     }
    5623              : 
    5624         2112 :   if (code->op == EXEC_DO_CONCURRENT)
    5625              :     {
    5626          148 :       gfc_init_block (&body);
    5627          148 :       cycle_label = gfc_build_label_decl (NULL_TREE);
    5628          148 :       code->cycle_label = cycle_label;
    5629              : 
    5630              :       /* Handle LOCAL and LOCAL_INIT.  */
    5631          148 :       std::vector<symbol_and_tree_t> saved_decls;
    5632          148 :       gfc_trans_concurrent_locality_spec (false, &body, &saved_decls,
    5633          148 :                                           code->ext.concur.locality);
    5634              : 
    5635              :       /* Translate the body.  */
    5636          148 :       tmp = gfc_trans_code (code->block->next);
    5637          148 :       gfc_add_expr_to_block (&body, tmp);
    5638              : 
    5639              :       /* Reset locality variables. */
    5640          148 :       gfc_trans_concurrent_locality_spec (true, &body, &saved_decls,
    5641              :                                           code->ext.concur.locality);
    5642          148 :       if (TREE_USED (cycle_label))
    5643              :         {
    5644          148 :           tmp = build1_v (LABEL_EXPR, cycle_label);
    5645          148 :           gfc_add_expr_to_block (&body, tmp);
    5646              :         }
    5647              : 
    5648          148 :       tmp = gfc_finish_block (&body);
    5649          148 :       nested_forall_info->do_concurrent = true;
    5650          148 :       tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
    5651          148 :       gfc_add_expr_to_block (&block, tmp);
    5652          148 :       goto done;
    5653          148 :     }
    5654              : 
    5655         1964 :   c = code->block->next;
    5656              : 
    5657              :   /* TODO: loop merging in FORALL statements.  */
    5658              :   /* Now that we've got a copy of the mask, generate the assignment loops.  */
    5659         3946 :   while (c)
    5660              :     {
    5661         1982 :       switch (c->op)
    5662              :         {
    5663         1826 :         case EXEC_ASSIGN:
    5664              :           /* A scalar or array assignment.  DO the simple check for
    5665              :              lhs to rhs dependencies.  These make a temporary for the
    5666              :              rhs and form a second forall block to copy to variable.  */
    5667         1826 :           need_temp = check_forall_dependencies(c, &pre, &post);
    5668              : 
    5669              :           /* Temporaries due to array assignment data dependencies introduce
    5670              :              no end of problems.  */
    5671         1826 :           if (need_temp || flag_test_forall_temp)
    5672          197 :             gfc_trans_assign_need_temp (c->expr1, c->expr2, NULL, false,
    5673              :                                         nested_forall_info, &block);
    5674              :           else
    5675              :             {
    5676              :               /* Use the normal assignment copying routines.  */
    5677         1629 :               assign = gfc_trans_assignment (c->expr1, c->expr2, false, true);
    5678              : 
    5679              :               /* Generate body and loops.  */
    5680         1629 :               tmp = gfc_trans_nested_forall_loop (nested_forall_info,
    5681              :                                                   assign, 1);
    5682         1629 :               gfc_add_expr_to_block (&block, tmp);
    5683              :             }
    5684              : 
    5685              :           /* Cleanup any temporary symtrees that have been made to deal
    5686              :              with dependencies.  */
    5687         1826 :           if (new_symtree)
    5688           62 :             cleanup_forall_symtrees (c);
    5689              : 
    5690              :           break;
    5691              : 
    5692           47 :         case EXEC_WHERE:
    5693              :           /* Translate WHERE or WHERE construct nested in FORALL.  */
    5694           47 :           gfc_trans_where_2 (c, NULL, false, nested_forall_info, &block);
    5695           47 :           break;
    5696              : 
    5697              :         /* Pointer assignment inside FORALL.  */
    5698           27 :         case EXEC_POINTER_ASSIGN:
    5699           27 :           need_temp = gfc_check_dependency (c->expr1, c->expr2, 0);
    5700              :           /* Avoid cases where a temporary would never be needed and where
    5701              :              the temp code is guaranteed to fail.  */
    5702           27 :           if (need_temp
    5703            7 :               || (flag_test_forall_temp
    5704            0 :                   && c->expr2->expr_type != EXPR_CONSTANT
    5705            0 :                   && c->expr2->expr_type != EXPR_NULL))
    5706           20 :             gfc_trans_pointer_assign_need_temp (c->expr1, c->expr2,
    5707              :                                                 nested_forall_info, &block);
    5708              :           else
    5709              :             {
    5710              :               /* Use the normal assignment copying routines.  */
    5711            7 :               assign = gfc_trans_pointer_assignment (c->expr1, c->expr2);
    5712              : 
    5713              :               /* Generate body and loops.  */
    5714            7 :               tmp = gfc_trans_nested_forall_loop (nested_forall_info,
    5715              :                                                   assign, 1);
    5716            7 :               gfc_add_expr_to_block (&block, tmp);
    5717              :             }
    5718              :           break;
    5719              : 
    5720           76 :         case EXEC_FORALL:
    5721           76 :           tmp = gfc_trans_forall_1 (c, nested_forall_info);
    5722           76 :           gfc_add_expr_to_block (&block, tmp);
    5723           76 :           break;
    5724              : 
    5725              :         /* Explicit subroutine calls are prevented by the frontend but interface
    5726              :            assignments can legitimately produce them.  */
    5727            6 :         case EXEC_ASSIGN_CALL:
    5728            6 :           assign = gfc_trans_call (c, true, NULL_TREE, NULL_TREE, false);
    5729            6 :           tmp = gfc_trans_nested_forall_loop (nested_forall_info, assign, 1);
    5730            6 :           gfc_add_expr_to_block (&block, tmp);
    5731            6 :           break;
    5732              : 
    5733            0 :         default:
    5734            0 :           gcc_unreachable ();
    5735              :         }
    5736              : 
    5737         1982 :       c = c->next;
    5738              :     }
    5739              : 
    5740         1964 : done:
    5741              :   /* Restore the original index variables.  */
    5742         6135 :   for (fa = code->ext.concur.forall_iterator, n = 0; fa; fa = fa->next, n++)
    5743         4023 :     gfc_restore_sym (fa->var->symtree->n.sym, &saved_vars[n]);
    5744              : 
    5745              :   /* Free the space for var, start, end, step, varexpr.  */
    5746         2112 :   free (var);
    5747         2112 :   free (start);
    5748         2112 :   free (end);
    5749         2112 :   free (step);
    5750         2112 :   free (varexpr);
    5751         2112 :   free (saved_vars);
    5752              : 
    5753         6135 :   for (this_forall = info->this_loop; this_forall;)
    5754              :     {
    5755         4023 :       iter_info *next = this_forall->next;
    5756         4023 :       free (this_forall);
    5757         4023 :       this_forall = next;
    5758              :     }
    5759              : 
    5760              :   /* Free the space for this forall_info.  */
    5761         2112 :   free (info);
    5762              : 
    5763         2112 :   if (pmask)
    5764              :     {
    5765              :       /* Free the temporary for the mask.  */
    5766           53 :       tmp = gfc_call_free (pmask);
    5767           53 :       gfc_add_expr_to_block (&block, tmp);
    5768              :     }
    5769         2112 :   if (maskindex)
    5770          725 :     pushdecl (maskindex);
    5771              : 
    5772         2112 :   gfc_add_block_to_block (&pre, &block);
    5773         2112 :   gfc_add_block_to_block (&pre, &post);
    5774              : 
    5775         2112 :   return gfc_finish_block (&pre);
    5776              : }
    5777              : 
    5778              : 
    5779              : /* Translate the FORALL statement or construct.  */
    5780              : 
    5781         1889 : tree gfc_trans_forall (gfc_code * code)
    5782              : {
    5783         1889 :   return gfc_trans_forall_1 (code, NULL);
    5784              : }
    5785              : 
    5786              : 
    5787              : /* Translate the DO CONCURRENT construct.  */
    5788              : 
    5789          148 : tree gfc_trans_do_concurrent (gfc_code * code)
    5790              : {
    5791          148 :   return gfc_trans_forall_1 (code, NULL);
    5792              : }
    5793              : 
    5794              : 
    5795              : /* Evaluate the WHERE mask expression, copy its value to a temporary.
    5796              :    If the WHERE construct is nested in FORALL, compute the overall temporary
    5797              :    needed by the WHERE mask expression multiplied by the iterator number of
    5798              :    the nested forall.
    5799              :    ME is the WHERE mask expression.
    5800              :    MASK is the current execution mask upon input, whose sense may or may
    5801              :    not be inverted as specified by the INVERT argument.
    5802              :    CMASK is the updated execution mask on output, or NULL if not required.
    5803              :    PMASK is the pending execution mask on output, or NULL if not required.
    5804              :    BLOCK is the block in which to place the condition evaluation loops.  */
    5805              : 
    5806              : static void
    5807          528 : gfc_evaluate_where_mask (gfc_expr * me, forall_info * nested_forall_info,
    5808              :                          tree mask, bool invert, tree cmask, tree pmask,
    5809              :                          tree mask_type, stmtblock_t * block)
    5810              : {
    5811          528 :   tree tmp, tmp1;
    5812          528 :   gfc_ss *lss, *rss;
    5813          528 :   gfc_loopinfo loop;
    5814          528 :   stmtblock_t body, body1;
    5815          528 :   tree count, cond, mtmp;
    5816          528 :   gfc_se lse, rse;
    5817              : 
    5818          528 :   gfc_init_loopinfo (&loop);
    5819              : 
    5820          528 :   lss = gfc_walk_expr (me);
    5821          528 :   rss = gfc_walk_expr (me);
    5822              : 
    5823              :   /* Variable to index the temporary.  */
    5824          528 :   count = gfc_create_var (gfc_array_index_type, "count");
    5825              :   /* Initialize count.  */
    5826          528 :   gfc_add_modify (block, count, gfc_index_zero_node);
    5827              : 
    5828          528 :   gfc_start_block (&body);
    5829              : 
    5830          528 :   gfc_init_se (&rse, NULL);
    5831          528 :   gfc_init_se (&lse, NULL);
    5832              : 
    5833          528 :   if (lss == gfc_ss_terminator)
    5834              :     {
    5835            0 :       gfc_init_block (&body1);
    5836              :     }
    5837              :   else
    5838              :     {
    5839              :       /* Initialize the loop.  */
    5840          528 :       gfc_init_loopinfo (&loop);
    5841              : 
    5842              :       /* We may need LSS to determine the shape of the expression.  */
    5843          528 :       gfc_add_ss_to_loop (&loop, lss);
    5844          528 :       gfc_add_ss_to_loop (&loop, rss);
    5845              : 
    5846          528 :       gfc_conv_ss_startstride (&loop);
    5847          528 :       gfc_conv_loop_setup (&loop, &me->where);
    5848              : 
    5849          528 :       gfc_mark_ss_chain_used (rss, 1);
    5850              :       /* Start the loop body.  */
    5851          528 :       gfc_start_scalarized_body (&loop, &body1);
    5852              : 
    5853              :       /* Translate the expression.  */
    5854          528 :       gfc_copy_loopinfo_to_se (&rse, &loop);
    5855          528 :       rse.ss = rss;
    5856          528 :       gfc_conv_expr (&rse, me);
    5857              :     }
    5858              : 
    5859              :   /* Variable to evaluate mask condition.  */
    5860          528 :   cond = gfc_create_var (mask_type, "cond");
    5861          528 :   if (mask && (cmask || pmask))
    5862          234 :     mtmp = gfc_create_var (mask_type, "mask");
    5863              :   else mtmp = NULL_TREE;
    5864              : 
    5865          528 :   gfc_add_block_to_block (&body1, &lse.pre);
    5866          528 :   gfc_add_block_to_block (&body1, &rse.pre);
    5867              : 
    5868          528 :   gfc_add_modify (&body1, cond, fold_convert (mask_type, rse.expr));
    5869              : 
    5870          528 :   if (mask && (cmask || pmask))
    5871              :     {
    5872          234 :       tmp = gfc_build_array_ref (mask, count, NULL);
    5873          234 :       if (invert)
    5874           99 :         tmp = fold_build1_loc (input_location, TRUTH_NOT_EXPR, mask_type, tmp);
    5875          234 :       gfc_add_modify (&body1, mtmp, tmp);
    5876              :     }
    5877              : 
    5878          528 :   if (cmask)
    5879              :     {
    5880          510 :       tmp1 = gfc_build_array_ref (cmask, count, NULL);
    5881          510 :       tmp = cond;
    5882          510 :       if (mask)
    5883          234 :         tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, mask_type,
    5884              :                                mtmp, tmp);
    5885          510 :       gfc_add_modify (&body1, tmp1, tmp);
    5886              :     }
    5887              : 
    5888          528 :   if (pmask)
    5889              :     {
    5890          146 :       tmp1 = gfc_build_array_ref (pmask, count, NULL);
    5891          146 :       tmp = fold_build1_loc (input_location, TRUTH_NOT_EXPR, mask_type, cond);
    5892          146 :       if (mask)
    5893          146 :         tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, mask_type, mtmp,
    5894              :                                tmp);
    5895          146 :       gfc_add_modify (&body1, tmp1, tmp);
    5896              :     }
    5897              : 
    5898          528 :   gfc_add_block_to_block (&body1, &lse.post);
    5899          528 :   gfc_add_block_to_block (&body1, &rse.post);
    5900              : 
    5901          528 :   if (lss == gfc_ss_terminator)
    5902              :     {
    5903            0 :       gfc_add_block_to_block (&body, &body1);
    5904              :     }
    5905              :   else
    5906              :     {
    5907              :       /* Increment count.  */
    5908          528 :       tmp1 = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
    5909              :                               count, gfc_index_one_node);
    5910          528 :       gfc_add_modify (&body1, count, tmp1);
    5911              : 
    5912              :       /* Generate the copying loops.  */
    5913          528 :       gfc_trans_scalarizing_loops (&loop, &body1);
    5914              : 
    5915          528 :       gfc_add_block_to_block (&body, &loop.pre);
    5916          528 :       gfc_add_block_to_block (&body, &loop.post);
    5917              : 
    5918          528 :       gfc_cleanup_loop (&loop);
    5919              :       /* TODO: Reuse lss and rss when copying temp->lhs.  Need to be careful
    5920              :          as tree nodes in SS may not be valid in different scope.  */
    5921              :     }
    5922              : 
    5923          528 :   tmp1 = gfc_finish_block (&body);
    5924              :   /* If the WHERE construct is inside FORALL, fill the full temporary.  */
    5925          528 :   if (nested_forall_info != NULL)
    5926           65 :     tmp1 = gfc_trans_nested_forall_loop (nested_forall_info, tmp1, 1);
    5927              : 
    5928          528 :   gfc_add_expr_to_block (block, tmp1);
    5929          528 : }
    5930              : 
    5931              : 
    5932              : /* Translate an assignment statement in a WHERE statement or construct
    5933              :    statement. The MASK expression is used to control which elements
    5934              :    of EXPR1 shall be assigned.  The sense of MASK is specified by
    5935              :    INVERT.  */
    5936              : 
    5937              : static tree
    5938          545 : gfc_trans_where_assign (gfc_expr *expr1, gfc_expr *expr2,
    5939              :                         tree mask, bool invert,
    5940              :                         tree count1, tree count2,
    5941              :                         gfc_code *cnext)
    5942              : {
    5943          545 :   gfc_se lse;
    5944          545 :   gfc_se rse;
    5945          545 :   gfc_ss *lss;
    5946          545 :   gfc_ss *lss_section;
    5947          545 :   gfc_ss *rss;
    5948              : 
    5949          545 :   gfc_loopinfo loop;
    5950          545 :   tree tmp;
    5951          545 :   stmtblock_t block;
    5952          545 :   stmtblock_t body;
    5953          545 :   tree index, maskexpr;
    5954              : 
    5955              :   /* A defined assignment.  */
    5956          545 :   if (cnext && cnext->resolved_sym)
    5957           44 :     return gfc_trans_call (cnext, true, mask, count1, invert);
    5958              : 
    5959              : #if 0
    5960              :   /* TODO: handle this special case.
    5961              :      Special case a single function returning an array.  */
    5962              :   if (expr2->expr_type == EXPR_FUNCTION && expr2->rank > 0)
    5963              :     {
    5964              :       tmp = gfc_trans_arrayfunc_assign (expr1, expr2);
    5965              :       if (tmp)
    5966              :         return tmp;
    5967              :     }
    5968              : #endif
    5969              : 
    5970              :  /* Assignment of the form lhs = rhs.  */
    5971          501 :   gfc_start_block (&block);
    5972              : 
    5973          501 :   gfc_init_se (&lse, NULL);
    5974          501 :   gfc_init_se (&rse, NULL);
    5975              : 
    5976              :   /* Walk the lhs.  */
    5977          501 :   lss = gfc_walk_expr (expr1);
    5978          501 :   rss = NULL;
    5979              : 
    5980              :   /* In each where-assign-stmt, the mask-expr and the variable being
    5981              :      defined shall be arrays of the same shape.  */
    5982          501 :   gcc_assert (lss != gfc_ss_terminator);
    5983              : 
    5984              :   /* The assignment needs scalarization.  */
    5985              :   lss_section = lss;
    5986              : 
    5987              :   /* Find a non-scalar SS from the lhs.  */
    5988              :   while (lss_section != gfc_ss_terminator
    5989          501 :          && lss_section->info->type != GFC_SS_SECTION)
    5990            0 :     lss_section = lss_section->next;
    5991              : 
    5992          501 :   gcc_assert (lss_section != gfc_ss_terminator);
    5993              : 
    5994              :   /* Initialize the scalarizer.  */
    5995          501 :   gfc_init_loopinfo (&loop);
    5996              : 
    5997              :   /* Walk the rhs.  */
    5998          501 :   rss = gfc_walk_expr (expr2);
    5999          501 :   if (rss == gfc_ss_terminator)
    6000              :     {
    6001              :       /* The rhs is scalar.  Add a ss for the expression.  */
    6002          343 :       rss = gfc_get_scalar_ss (gfc_ss_terminator, expr2);
    6003          343 :       rss->info->where = 1;
    6004              :     }
    6005              : 
    6006              :   /* Associate the SS with the loop.  */
    6007          501 :   gfc_add_ss_to_loop (&loop, lss);
    6008          501 :   gfc_add_ss_to_loop (&loop, rss);
    6009              : 
    6010              :   /* Calculate the bounds of the scalarization.  */
    6011          501 :   gfc_conv_ss_startstride (&loop);
    6012              : 
    6013              :   /* Resolve any data dependencies in the statement.  */
    6014          501 :   gfc_conv_resolve_dependencies (&loop, lss_section, rss);
    6015              : 
    6016              :   /* Setup the scalarizing loops.  */
    6017          501 :   gfc_conv_loop_setup (&loop, &expr2->where);
    6018              : 
    6019              :   /* Setup the gfc_se structures.  */
    6020          501 :   gfc_copy_loopinfo_to_se (&lse, &loop);
    6021          501 :   gfc_copy_loopinfo_to_se (&rse, &loop);
    6022              : 
    6023          501 :   rse.ss = rss;
    6024          501 :   gfc_mark_ss_chain_used (rss, 1);
    6025          501 :   if (loop.temp_ss == NULL)
    6026              :     {
    6027          422 :       lse.ss = lss;
    6028          422 :       gfc_mark_ss_chain_used (lss, 1);
    6029              :     }
    6030              :   else
    6031              :     {
    6032           79 :       lse.ss = loop.temp_ss;
    6033           79 :       gfc_mark_ss_chain_used (lss, 3);
    6034           79 :       gfc_mark_ss_chain_used (loop.temp_ss, 3);
    6035              :     }
    6036              : 
    6037              :   /* Start the scalarized loop body.  */
    6038          501 :   gfc_start_scalarized_body (&loop, &body);
    6039              : 
    6040              :   /* Translate the expression.  */
    6041          501 :   gfc_conv_expr (&rse, expr2);
    6042          501 :   if (lss != gfc_ss_terminator && loop.temp_ss != NULL)
    6043           79 :     gfc_conv_tmp_array_ref (&lse);
    6044              :   else
    6045          422 :     gfc_conv_expr (&lse, expr1);
    6046              : 
    6047              :   /* Form the mask expression according to the mask.  */
    6048          501 :   index = count1;
    6049          501 :   maskexpr = gfc_build_array_ref (mask, index, NULL);
    6050          501 :   if (invert)
    6051           24 :     maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
    6052           24 :                                 TREE_TYPE (maskexpr), maskexpr);
    6053              : 
    6054              :   /* Use the scalar assignment as is.  */
    6055         1002 :   tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts,
    6056          501 :                                  false, loop.temp_ss == NULL);
    6057              : 
    6058          501 :   tmp = build3_v (COND_EXPR, maskexpr, tmp, build_empty_stmt (input_location));
    6059              : 
    6060          501 :   gfc_add_expr_to_block (&body, tmp);
    6061              : 
    6062          501 :   if (lss == gfc_ss_terminator)
    6063              :     {
    6064              :       /* Increment count1.  */
    6065              :       tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
    6066              :                              count1, gfc_index_one_node);
    6067              :       gfc_add_modify (&body, count1, tmp);
    6068              : 
    6069              :       /* Use the scalar assignment as is.  */
    6070              :       gfc_add_block_to_block (&block, &body);
    6071              :     }
    6072              :   else
    6073              :     {
    6074          501 :       gcc_assert (lse.ss == gfc_ss_terminator
    6075              :                   && rse.ss == gfc_ss_terminator);
    6076              : 
    6077          501 :       if (loop.temp_ss != NULL)
    6078              :         {
    6079              :           /* Increment count1 before finish the main body of a scalarized
    6080              :              expression.  */
    6081           79 :           tmp = fold_build2_loc (input_location, PLUS_EXPR,
    6082              :                                  gfc_array_index_type, count1, gfc_index_one_node);
    6083           79 :           gfc_add_modify (&body, count1, tmp);
    6084           79 :           gfc_trans_scalarized_loop_boundary (&loop, &body);
    6085              : 
    6086              :           /* We need to copy the temporary to the actual lhs.  */
    6087           79 :           gfc_init_se (&lse, NULL);
    6088           79 :           gfc_init_se (&rse, NULL);
    6089           79 :           gfc_copy_loopinfo_to_se (&lse, &loop);
    6090           79 :           gfc_copy_loopinfo_to_se (&rse, &loop);
    6091              : 
    6092           79 :           rse.ss = loop.temp_ss;
    6093           79 :           lse.ss = lss;
    6094              : 
    6095           79 :           gfc_conv_tmp_array_ref (&rse);
    6096           79 :           gfc_conv_expr (&lse, expr1);
    6097              : 
    6098           79 :           gcc_assert (lse.ss == gfc_ss_terminator
    6099              :                       && rse.ss == gfc_ss_terminator);
    6100              : 
    6101              :           /* Form the mask expression according to the mask tree list.  */
    6102           79 :           index = count2;
    6103           79 :           maskexpr = gfc_build_array_ref (mask, index, NULL);
    6104           79 :           if (invert)
    6105            0 :             maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
    6106            0 :                                         TREE_TYPE (maskexpr), maskexpr);
    6107              : 
    6108              :           /* Use the scalar assignment as is.  */
    6109           79 :           tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts, false, true);
    6110           79 :           tmp = build3_v (COND_EXPR, maskexpr, tmp,
    6111              :                           build_empty_stmt (input_location));
    6112           79 :           gfc_add_expr_to_block (&body, tmp);
    6113              : 
    6114              :           /* Increment count2.  */
    6115           79 :           tmp = fold_build2_loc (input_location, PLUS_EXPR,
    6116              :                                  gfc_array_index_type, count2,
    6117              :                                  gfc_index_one_node);
    6118           79 :           gfc_add_modify (&body, count2, tmp);
    6119              :         }
    6120              :       else
    6121              :         {
    6122              :           /* Increment count1.  */
    6123          422 :           tmp = fold_build2_loc (input_location, PLUS_EXPR,
    6124              :                                  gfc_array_index_type, count1,
    6125              :                                  gfc_index_one_node);
    6126          422 :           gfc_add_modify (&body, count1, tmp);
    6127              :         }
    6128              : 
    6129              :       /* Generate the copying loops.  */
    6130          501 :       gfc_trans_scalarizing_loops (&loop, &body);
    6131              : 
    6132              :       /* Wrap the whole thing up.  */
    6133          501 :       gfc_add_block_to_block (&block, &loop.pre);
    6134          501 :       gfc_add_block_to_block (&block, &loop.post);
    6135          501 :       gfc_cleanup_loop (&loop);
    6136              :     }
    6137              : 
    6138          501 :   return gfc_finish_block (&block);
    6139              : }
    6140              : 
    6141              : 
    6142              : /* Translate the WHERE construct or statement.
    6143              :    This function can be called iteratively to translate the nested WHERE
    6144              :    construct or statement.
    6145              :    MASK is the control mask.  */
    6146              : 
    6147              : static void
    6148          350 : gfc_trans_where_2 (gfc_code * code, tree mask, bool invert,
    6149              :                    forall_info * nested_forall_info, stmtblock_t * block)
    6150              : {
    6151          350 :   stmtblock_t inner_size_body;
    6152          350 :   tree inner_size, size;
    6153          350 :   gfc_ss *lss, *rss;
    6154          350 :   tree mask_type;
    6155          350 :   gfc_expr *expr1;
    6156          350 :   gfc_expr *expr2;
    6157          350 :   gfc_code *cblock;
    6158          350 :   gfc_code *cnext;
    6159          350 :   tree tmp;
    6160          350 :   tree cond;
    6161          350 :   tree count1, count2;
    6162          350 :   bool need_cmask;
    6163          350 :   bool need_pmask;
    6164          350 :   int need_temp;
    6165          350 :   tree pcmask = NULL_TREE;
    6166          350 :   tree ppmask = NULL_TREE;
    6167          350 :   tree cmask = NULL_TREE;
    6168          350 :   tree pmask = NULL_TREE;
    6169          350 :   gfc_actual_arglist *arg;
    6170              : 
    6171              :   /* the WHERE statement or the WHERE construct statement.  */
    6172          350 :   cblock = code->block;
    6173              : 
    6174              :   /* As the mask array can be very big, prefer compact boolean types.  */
    6175          350 :   mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
    6176              : 
    6177              :   /* Determine which temporary masks are needed.  */
    6178          350 :   if (!cblock->block)
    6179              :     {
    6180              :       /* One clause: No ELSEWHEREs.  */
    6181          169 :       need_cmask = (cblock->next != 0);
    6182          169 :       need_pmask = false;
    6183              :     }
    6184          181 :   else if (cblock->block->block)
    6185              :     {
    6186              :       /* Three or more clauses: Conditional ELSEWHEREs.  */
    6187              :       need_cmask = true;
    6188              :       need_pmask = true;
    6189              :     }
    6190          102 :   else if (cblock->next)
    6191              :     {
    6192              :       /* Two clauses, the first non-empty.  */
    6193           84 :       need_cmask = true;
    6194           84 :       need_pmask = (mask != NULL_TREE
    6195           84 :                     && cblock->block->next != 0);
    6196              :     }
    6197           18 :   else if (!cblock->block->next)
    6198              :     {
    6199              :       /* Two clauses, both empty.  */
    6200              :       need_cmask = false;
    6201              :       need_pmask = false;
    6202              :     }
    6203              :   /* Two clauses, the first empty, the second non-empty.  */
    6204            9 :   else if (mask)
    6205              :     {
    6206            0 :       need_cmask = (cblock->block->expr1 != 0);
    6207            0 :       need_pmask = true;
    6208              :     }
    6209              :   else
    6210              :     {
    6211              :       need_cmask = true;
    6212              :       need_pmask = false;
    6213              :     }
    6214              : 
    6215          169 :   if (need_cmask || need_pmask)
    6216              :     {
    6217              :       /* Calculate the size of temporary needed by the mask-expr.  */
    6218          332 :       gfc_init_block (&inner_size_body);
    6219          332 :       inner_size = compute_inner_temp_size (cblock->expr1, cblock->expr1,
    6220              :                                             &inner_size_body, &lss, &rss);
    6221              : 
    6222          332 :       gfc_free_ss_chain (lss);
    6223          332 :       gfc_free_ss_chain (rss);
    6224              : 
    6225              :       /* Calculate the total size of temporary needed.  */
    6226          332 :       size = compute_overall_iter_number (nested_forall_info, inner_size,
    6227              :                                           &inner_size_body, block);
    6228              : 
    6229              :       /* Check whether the size is negative.  */
    6230          332 :       cond = fold_build2_loc (input_location, LE_EXPR, logical_type_node, size,
    6231              :                               gfc_index_zero_node);
    6232          332 :       size = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
    6233              :                               cond, gfc_index_zero_node, size);
    6234          332 :       size = gfc_evaluate_now (size, block);
    6235              : 
    6236              :       /* Allocate temporary for WHERE mask if needed.  */
    6237          332 :       if (need_cmask)
    6238          332 :         cmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
    6239              :                                                  &pcmask);
    6240              : 
    6241              :       /* Allocate temporary for !mask if needed.  */
    6242          332 :       if (need_pmask)
    6243           83 :         pmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
    6244              :                                                  &ppmask);
    6245              :     }
    6246              : 
    6247          996 :   while (cblock)
    6248              :     {
    6249              :       /* Each time around this loop, the where clause is conditional
    6250              :          on the value of mask and invert, which are updated at the
    6251              :          bottom of the loop.  */
    6252              : 
    6253              :       /* Has mask-expr.  */
    6254          646 :       if (cblock->expr1)
    6255              :         {
    6256              :           /* Ensure that the WHERE mask will be evaluated exactly once.
    6257              :              If there are no statements in this WHERE/ELSEWHERE clause,
    6258              :              then we don't need to update the control mask (cmask).
    6259              :              If this is the last clause of the WHERE construct, then
    6260              :              we don't need to update the pending control mask (pmask).  */
    6261          528 :           if (mask)
    6262          234 :             gfc_evaluate_where_mask (cblock->expr1, nested_forall_info,
    6263              :                                      mask, invert,
    6264          234 :                                      cblock->next  ? cmask : NULL_TREE,
    6265          234 :                                      cblock->block ? pmask : NULL_TREE,
    6266              :                                      mask_type, block);
    6267              :           else
    6268          294 :             gfc_evaluate_where_mask (cblock->expr1, nested_forall_info,
    6269              :                                      NULL_TREE, false,
    6270          294 :                                      (cblock->next || cblock->block)
    6271              :                                      ? cmask : NULL_TREE,
    6272              :                                      NULL_TREE, mask_type, block);
    6273              : 
    6274              :           invert = false;
    6275              :         }
    6276              :       /* It's a final elsewhere-stmt. No mask-expr is present.  */
    6277              :       else
    6278              :         cmask = mask;
    6279              : 
    6280              :       /* The body of this where clause are controlled by cmask with
    6281              :          sense specified by invert.  */
    6282              : 
    6283              :       /* Get the assignment statement of a WHERE statement, or the first
    6284              :          statement in where-body-construct of a WHERE construct.  */
    6285          646 :       cnext = cblock->next;
    6286         1274 :       while (cnext)
    6287              :         {
    6288          628 :           switch (cnext->op)
    6289              :             {
    6290              :             /* WHERE assignment statement.  */
    6291           44 :             case EXEC_ASSIGN_CALL:
    6292              : 
    6293           44 :               arg = cnext->ext.actual;
    6294           44 :               expr1 = expr2 = NULL;
    6295          132 :               for (; arg; arg = arg->next)
    6296              :                 {
    6297           88 :                   if (!arg->expr)
    6298            0 :                     continue;
    6299           88 :                   if (expr1 == NULL)
    6300              :                     expr1 = arg->expr;
    6301              :                   else
    6302           44 :                     expr2 = arg->expr;
    6303              :                 }
    6304           44 :               goto evaluate;
    6305              : 
    6306          528 :             case EXEC_ASSIGN:
    6307          528 :               expr1 = cnext->expr1;
    6308          528 :               expr2 = cnext->expr2;
    6309          572 :     evaluate:
    6310          572 :               if (nested_forall_info != NULL)
    6311              :                 {
    6312           66 :                   need_temp = gfc_check_dependency (expr1, expr2, 0);
    6313           66 :                   if ((need_temp || flag_test_forall_temp)
    6314           28 :                     && cnext->op != EXEC_ASSIGN_CALL)
    6315           27 :                     gfc_trans_assign_need_temp (expr1, expr2,
    6316              :                                                 cmask, invert,
    6317              :                                                 nested_forall_info, block);
    6318              :                   else
    6319              :                     {
    6320              :                       /* Variables to control maskexpr.  */
    6321           39 :                       count1 = gfc_create_var (gfc_array_index_type, "count1");
    6322           39 :                       count2 = gfc_create_var (gfc_array_index_type, "count2");
    6323           39 :                       gfc_add_modify (block, count1, gfc_index_zero_node);
    6324           39 :                       gfc_add_modify (block, count2, gfc_index_zero_node);
    6325              : 
    6326           39 :                       tmp = gfc_trans_where_assign (expr1, expr2,
    6327              :                                                     cmask, invert,
    6328              :                                                     count1, count2,
    6329              :                                                     cnext);
    6330              : 
    6331           39 :                       tmp = gfc_trans_nested_forall_loop (nested_forall_info,
    6332              :                                                           tmp, 1);
    6333           39 :                       gfc_add_expr_to_block (block, tmp);
    6334              :                     }
    6335              :                 }
    6336              :               else
    6337              :                 {
    6338              :                   /* Variables to control maskexpr.  */
    6339          506 :                   count1 = gfc_create_var (gfc_array_index_type, "count1");
    6340          506 :                   count2 = gfc_create_var (gfc_array_index_type, "count2");
    6341          506 :                   gfc_add_modify (block, count1, gfc_index_zero_node);
    6342          506 :                   gfc_add_modify (block, count2, gfc_index_zero_node);
    6343              : 
    6344          506 :                   tmp = gfc_trans_where_assign (expr1, expr2,
    6345              :                                                 cmask, invert,
    6346              :                                                 count1, count2,
    6347              :                                                 cnext);
    6348          506 :                   gfc_add_expr_to_block (block, tmp);
    6349              : 
    6350              :                 }
    6351              :               break;
    6352              : 
    6353              :             /* WHERE or WHERE construct is part of a where-body-construct.  */
    6354           56 :             case EXEC_WHERE:
    6355           56 :               gfc_trans_where_2 (cnext, cmask, invert,
    6356              :                                  nested_forall_info, block);
    6357           56 :               break;
    6358              : 
    6359            0 :             default:
    6360            0 :               gcc_unreachable ();
    6361              :             }
    6362              : 
    6363              :          /* The next statement within the same where-body-construct.  */
    6364          628 :          cnext = cnext->next;
    6365              :        }
    6366              :     /* The next masked-elsewhere-stmt, elsewhere-stmt, or end-where-stmt.  */
    6367          646 :     cblock = cblock->block;
    6368          646 :     if (mask == NULL_TREE)
    6369              :       {
    6370              :         /* If we're the initial WHERE, we can simply invert the sense
    6371              :            of the current mask to obtain the "mask" for the remaining
    6372              :            ELSEWHEREs.  */
    6373              :         invert = true;
    6374              :         mask = cmask;
    6375              :       }
    6376              :     else
    6377              :       {
    6378              :         /* Otherwise, for nested WHERE's we need to use the pending mask.  */
    6379          343 :         invert = false;
    6380          343 :         mask = pmask;
    6381              :       }
    6382              :   }
    6383              : 
    6384              :   /* If we allocated a pending mask array, deallocate it now.  */
    6385          350 :   if (ppmask)
    6386              :     {
    6387            1 :       tmp = gfc_call_free (ppmask);
    6388            1 :       gfc_add_expr_to_block (block, tmp);
    6389              :     }
    6390              : 
    6391              :   /* If we allocated a current mask array, deallocate it now.  */
    6392          350 :   if (pcmask)
    6393              :     {
    6394           44 :       tmp = gfc_call_free (pcmask);
    6395           44 :       gfc_add_expr_to_block (block, tmp);
    6396              :     }
    6397          350 : }
    6398              : 
    6399              : /* Translate a simple WHERE construct or statement without dependencies.
    6400              :    CBLOCK is the "then" clause of the WHERE statement, where CBLOCK->EXPR
    6401              :    is the mask condition, and EBLOCK if non-NULL is the "else" clause.
    6402              :    Currently both CBLOCK and EBLOCK are restricted to single assignments.  */
    6403              : 
    6404              : static tree
    6405           96 : gfc_trans_where_3 (gfc_code * cblock, gfc_code * eblock)
    6406              : {
    6407           96 :   stmtblock_t block, body;
    6408           96 :   gfc_expr *cond, *tdst, *tsrc, *edst, *esrc;
    6409           96 :   tree tmp, cexpr, tstmt, estmt;
    6410           96 :   gfc_ss *css, *tdss, *tsss;
    6411           96 :   gfc_se cse, tdse, tsse, edse, esse;
    6412           96 :   gfc_loopinfo loop;
    6413           96 :   gfc_ss *edss = 0;
    6414           96 :   gfc_ss *esss = 0;
    6415           96 :   bool maybe_workshare = false;
    6416              : 
    6417              :   /* Allow the scalarizer to workshare simple where loops.  */
    6418           96 :   if ((ompws_flags & (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_BODY))
    6419              :       == OMPWS_WORKSHARE_FLAG)
    6420              :     {
    6421           13 :       maybe_workshare = true;
    6422           13 :       ompws_flags |= OMPWS_SCALARIZER_WS | OMPWS_SCALARIZER_BODY;
    6423              :     }
    6424              : 
    6425           96 :   cond = cblock->expr1;
    6426           96 :   tdst = cblock->next->expr1;
    6427           96 :   tsrc = cblock->next->expr2;
    6428           96 :   edst = eblock ? eblock->next->expr1 : NULL;
    6429           13 :   esrc = eblock ? eblock->next->expr2 : NULL;
    6430              : 
    6431           96 :   gfc_start_block (&block);
    6432           96 :   gfc_init_loopinfo (&loop);
    6433              : 
    6434              :   /* Handle the condition.  */
    6435           96 :   gfc_init_se (&cse, NULL);
    6436           96 :   css = gfc_walk_expr (cond);
    6437           96 :   gfc_add_ss_to_loop (&loop, css);
    6438              : 
    6439              :   /* Handle the then-clause.  */
    6440           96 :   gfc_init_se (&tdse, NULL);
    6441           96 :   gfc_init_se (&tsse, NULL);
    6442           96 :   tdss = gfc_walk_expr (tdst);
    6443           96 :   tsss = gfc_walk_expr (tsrc);
    6444           96 :   if (tsss == gfc_ss_terminator)
    6445              :     {
    6446           58 :       tsss = gfc_get_scalar_ss (gfc_ss_terminator, tsrc);
    6447           58 :       tsss->info->where = 1;
    6448              :     }
    6449           96 :   gfc_add_ss_to_loop (&loop, tdss);
    6450           96 :   gfc_add_ss_to_loop (&loop, tsss);
    6451              : 
    6452           96 :   if (eblock)
    6453              :     {
    6454              :       /* Handle the else clause.  */
    6455           13 :       gfc_init_se (&edse, NULL);
    6456           13 :       gfc_init_se (&esse, NULL);
    6457           13 :       edss = gfc_walk_expr (edst);
    6458           13 :       esss = gfc_walk_expr (esrc);
    6459           13 :       if (esss == gfc_ss_terminator)
    6460              :         {
    6461           13 :           esss = gfc_get_scalar_ss (gfc_ss_terminator, esrc);
    6462           13 :           esss->info->where = 1;
    6463              :         }
    6464           13 :       gfc_add_ss_to_loop (&loop, edss);
    6465           13 :       gfc_add_ss_to_loop (&loop, esss);
    6466              :     }
    6467              : 
    6468           96 :   gfc_conv_ss_startstride (&loop);
    6469           96 :   gfc_conv_loop_setup (&loop, &tdst->where);
    6470              : 
    6471           96 :   gfc_mark_ss_chain_used (css, 1);
    6472           96 :   gfc_mark_ss_chain_used (tdss, 1);
    6473           96 :   gfc_mark_ss_chain_used (tsss, 1);
    6474           96 :   if (eblock)
    6475              :     {
    6476           13 :       gfc_mark_ss_chain_used (edss, 1);
    6477           13 :       gfc_mark_ss_chain_used (esss, 1);
    6478              :     }
    6479              : 
    6480           96 :   gfc_start_scalarized_body (&loop, &body);
    6481              : 
    6482           96 :   gfc_copy_loopinfo_to_se (&cse, &loop);
    6483           96 :   gfc_copy_loopinfo_to_se (&tdse, &loop);
    6484           96 :   gfc_copy_loopinfo_to_se (&tsse, &loop);
    6485           96 :   cse.ss = css;
    6486           96 :   tdse.ss = tdss;
    6487           96 :   tsse.ss = tsss;
    6488           96 :   if (eblock)
    6489              :     {
    6490           13 :       gfc_copy_loopinfo_to_se (&edse, &loop);
    6491           13 :       gfc_copy_loopinfo_to_se (&esse, &loop);
    6492           13 :       edse.ss = edss;
    6493           13 :       esse.ss = esss;
    6494              :     }
    6495              : 
    6496           96 :   gfc_conv_expr (&cse, cond);
    6497           96 :   gfc_add_block_to_block (&body, &cse.pre);
    6498           96 :   cexpr = cse.expr;
    6499              : 
    6500           96 :   gfc_conv_expr (&tsse, tsrc);
    6501           96 :   if (tdss != gfc_ss_terminator && loop.temp_ss != NULL)
    6502            0 :     gfc_conv_tmp_array_ref (&tdse);
    6503              :   else
    6504           96 :     gfc_conv_expr (&tdse, tdst);
    6505              : 
    6506           96 :   if (eblock)
    6507              :     {
    6508           13 :       gfc_conv_expr (&esse, esrc);
    6509           13 :       if (edss != gfc_ss_terminator && loop.temp_ss != NULL)
    6510            0 :         gfc_conv_tmp_array_ref (&edse);
    6511              :       else
    6512           13 :         gfc_conv_expr (&edse, edst);
    6513              :     }
    6514              : 
    6515           96 :   tstmt = gfc_trans_scalar_assign (&tdse, &tsse, tdst->ts, false, true);
    6516           96 :   estmt = eblock ? gfc_trans_scalar_assign (&edse, &esse, edst->ts,
    6517              :                                             false, true)
    6518           83 :                  : build_empty_stmt (input_location);
    6519           96 :   tmp = build3_v (COND_EXPR, cexpr, tstmt, estmt);
    6520           96 :   gfc_add_expr_to_block (&body, tmp);
    6521           96 :   gfc_add_block_to_block (&body, &cse.post);
    6522              : 
    6523           96 :   if (maybe_workshare)
    6524           13 :     ompws_flags &= ~OMPWS_SCALARIZER_BODY;
    6525           96 :   gfc_trans_scalarizing_loops (&loop, &body);
    6526           96 :   gfc_add_block_to_block (&block, &loop.pre);
    6527           96 :   gfc_add_block_to_block (&block, &loop.post);
    6528           96 :   gfc_cleanup_loop (&loop);
    6529              : 
    6530           96 :   return gfc_finish_block (&block);
    6531              : }
    6532              : 
    6533              : /* As the WHERE or WHERE construct statement can be nested, we call
    6534              :    gfc_trans_where_2 to do the translation, and pass the initial
    6535              :    NULL values for both the control mask and the pending control mask.  */
    6536              : 
    6537              : tree
    6538          343 : gfc_trans_where (gfc_code * code)
    6539              : {
    6540          343 :   stmtblock_t block;
    6541          343 :   gfc_code *cblock;
    6542          343 :   gfc_code *eblock;
    6543              : 
    6544          343 :   cblock = code->block;
    6545          343 :   if (cblock->next
    6546          316 :       && cblock->next->op == EXEC_ASSIGN
    6547          271 :       && !cblock->next->next)
    6548              :     {
    6549          269 :       eblock = cblock->block;
    6550          269 :       if (!eblock)
    6551              :         {
    6552              :           /* A simple "WHERE (cond) x = y" statement or block is
    6553              :              dependence free if cond is not dependent upon writing x,
    6554              :              and the source y is unaffected by the destination x.  */
    6555          164 :           if (!gfc_check_dependency (cblock->next->expr1,
    6556              :                                      cblock->expr1, 0)
    6557          272 :               && !gfc_check_dependency (cblock->next->expr1,
    6558          108 :                                         cblock->next->expr2, 0))
    6559           83 :             return gfc_trans_where_3 (cblock, NULL);
    6560              :         }
    6561          105 :       else if (!eblock->expr1
    6562           35 :                && !eblock->block
    6563           35 :                && eblock->next
    6564           26 :                && eblock->next->op == EXEC_ASSIGN
    6565           25 :                && !eblock->next->next)
    6566              :         {
    6567              :           /* A simple "WHERE (cond) x1 = y1 ELSEWHERE x2 = y2 ENDWHERE"
    6568              :              block is dependence free if cond is not dependent on writes
    6569              :              to x1 and x2, y1 is not dependent on writes to x2, and y2
    6570              :              is not dependent on writes to x1, and both y's are not
    6571              :              dependent upon their own x's.  In addition to this, the
    6572              :              final two dependency checks below exclude all but the same
    6573              :              array reference if the where and elswhere destinations
    6574              :              are the same.  In short, this is VERY conservative and this
    6575              :              is needed because the two loops, required by the standard
    6576              :              are coalesced in gfc_trans_where_3.  */
    6577           25 :           if (!gfc_check_dependency (cblock->next->expr1,
    6578              :                                     cblock->expr1, 0)
    6579           25 :               && !gfc_check_dependency (eblock->next->expr1,
    6580              :                                        cblock->expr1, 0)
    6581           25 :               && !gfc_check_dependency (cblock->next->expr1,
    6582           25 :                                        eblock->next->expr2, 1)
    6583           19 :               && !gfc_check_dependency (eblock->next->expr1,
    6584           19 :                                        cblock->next->expr2, 1)
    6585           19 :               && !gfc_check_dependency (cblock->next->expr1,
    6586           19 :                                        cblock->next->expr2, 1)
    6587           19 :               && !gfc_check_dependency (eblock->next->expr1,
    6588           19 :                                        eblock->next->expr2, 1)
    6589           19 :               && !gfc_check_dependency (cblock->next->expr1,
    6590           19 :                                        eblock->next->expr1, 0)
    6591           44 :               && !gfc_check_dependency (eblock->next->expr1,
    6592           19 :                                        cblock->next->expr1, 0))
    6593           13 :             return gfc_trans_where_3 (cblock, eblock);
    6594              :         }
    6595              :     }
    6596              : 
    6597          247 :   gfc_start_block (&block);
    6598              : 
    6599          247 :   gfc_trans_where_2 (code, NULL, false, NULL, &block);
    6600              : 
    6601          247 :   return gfc_finish_block (&block);
    6602              : }
    6603              : 
    6604              : 
    6605              : /* CYCLE a DO loop. The label decl has already been created by
    6606              :    gfc_trans_do(), it's in TREE_PURPOSE (backend_decl) of the gfc_code
    6607              :    node at the head of the loop. We must mark the label as used.  */
    6608              : 
    6609              : tree
    6610          123 : gfc_trans_cycle (gfc_code * code)
    6611              : {
    6612          123 :   tree cycle_label;
    6613              : 
    6614          123 :   cycle_label = code->ext.which_construct->cycle_label;
    6615          123 :   gcc_assert (cycle_label);
    6616              : 
    6617          123 :   TREE_USED (cycle_label) = 1;
    6618          123 :   return build1_v (GOTO_EXPR, cycle_label);
    6619              : }
    6620              : 
    6621              : 
    6622              : /* EXIT a DO loop. Similar to CYCLE, but now the label is in
    6623              :    TREE_VALUE (backend_decl) of the gfc_code node at the head of the
    6624              :    loop.  */
    6625              : 
    6626              : tree
    6627          698 : gfc_trans_exit (gfc_code * code)
    6628              : {
    6629          698 :   tree exit_label;
    6630              : 
    6631          698 :   exit_label = code->ext.which_construct->exit_label;
    6632          698 :   gcc_assert (exit_label);
    6633              : 
    6634          698 :   TREE_USED (exit_label) = 1;
    6635          698 :   return build1_v (GOTO_EXPR, exit_label);
    6636              : }
    6637              : 
    6638              : 
    6639              : /* Get the initializer expression for the code and expr of an allocate.
    6640              :    When no initializer is needed return NULL.  */
    6641              : 
    6642              : static gfc_expr *
    6643        13300 : allocate_get_initializer (gfc_code * code, gfc_expr * expr)
    6644              : {
    6645        13300 :   if (!gfc_bt_struct (expr->ts.type) && expr->ts.type != BT_CLASS)
    6646              :     return NULL;
    6647              : 
    6648              :   /* An explicit type was given in allocate ( T:: object).  */
    6649         3839 :   if (code->ext.alloc.ts.type == BT_DERIVED
    6650         3839 :       && (code->ext.alloc.ts.u.derived->attr.alloc_comp
    6651          506 :           || gfc_has_default_initializer (code->ext.alloc.ts.u.derived)))
    6652          350 :     return gfc_default_initializer (&code->ext.alloc.ts);
    6653              : 
    6654          563 :   if (gfc_bt_struct (expr->ts.type)
    6655         3489 :       && (expr->ts.u.derived->attr.alloc_comp
    6656         1889 :           || gfc_has_default_initializer (expr->ts.u.derived)))
    6657         1492 :     return gfc_default_initializer (&expr->ts);
    6658              : 
    6659         1997 :   if (expr->ts.type == BT_CLASS
    6660         1997 :       && (CLASS_DATA (expr)->ts.u.derived->attr.alloc_comp
    6661          473 :           || gfc_has_default_initializer (CLASS_DATA (expr)->ts.u.derived)))
    6662          175 :     return gfc_default_initializer (&CLASS_DATA (expr)->ts);
    6663              : 
    6664              :   return NULL;
    6665              : }
    6666              : 
    6667              : /* Translate the ALLOCATE statement.  */
    6668              : 
    6669              : tree
    6670        14129 : gfc_trans_allocate (gfc_code * code, gfc_omp_namelist *omp_allocate)
    6671              : {
    6672        14129 :   gfc_alloc *al;
    6673        14129 :   gfc_expr *expr, *e3rhs = NULL, *init_expr;
    6674        14129 :   gfc_se se, se_sz;
    6675        14129 :   tree tmp;
    6676        14129 :   tree parm;
    6677        14129 :   tree stat;
    6678        14129 :   tree errmsg;
    6679        14129 :   tree errlen;
    6680        14129 :   tree label_errmsg;
    6681        14129 :   tree label_finish;
    6682        14129 :   tree memsz;
    6683        14129 :   tree al_vptr, al_len;
    6684              :   /* If an expr3 is present, then store the tree for accessing its
    6685              :      _vptr, and _len components in the variables, respectively.  The
    6686              :      element size, i.e. _vptr%size, is stored in expr3_esize.  Any of
    6687              :      the trees may be the NULL_TREE indicating that this is not
    6688              :      available for expr3's type.  */
    6689        14129 :   tree expr3, expr3_vptr, expr3_len, expr3_esize;
    6690              :   /* Classify what expr3 stores.  */
    6691        14129 :   enum { E3_UNSET = 0, E3_SOURCE, E3_MOLD, E3_DESC } e3_is;
    6692        14129 :   stmtblock_t block;
    6693        14129 :   stmtblock_t post;
    6694        14129 :   stmtblock_t final_block;
    6695        14129 :   bool upoly_expr, tmp_expr3_len_flag = false, al_len_needs_set, is_coarray;
    6696        14129 :   bool needs_caf_sync, caf_refs_comp;
    6697        14129 :   bool e3_has_nodescriptor = false;
    6698        14129 :   gfc_symtree *newsym = NULL;
    6699        14129 :   symbol_attribute caf_attr;
    6700        14129 :   gfc_actual_arglist *param_list;
    6701        14129 :   tree ts_string_length = NULL_TREE;
    6702              : 
    6703        14129 :   if (!code->ext.alloc.list)
    6704              :     return NULL_TREE;
    6705              : 
    6706        14129 :   stat = tmp = memsz = al_vptr = al_len = NULL_TREE;
    6707        14129 :   expr3 = expr3_vptr = expr3_len = expr3_esize = NULL_TREE;
    6708        14129 :   label_errmsg = label_finish = errmsg = errlen = NULL_TREE;
    6709        14129 :   e3_is = E3_UNSET;
    6710        14129 :   is_coarray = needs_caf_sync = false;
    6711              : 
    6712        14129 :   gfc_init_block (&block);
    6713        14129 :   gfc_init_block (&post);
    6714        14129 :   gfc_init_block (&final_block);
    6715              : 
    6716              :   /* STAT= (and maybe ERRMSG=) is present.  */
    6717        14129 :   if (code->expr1)
    6718              :     {
    6719              :       /* STAT=.  */
    6720          290 :       tree gfc_int4_type_node = gfc_get_int_type (4);
    6721          290 :       stat = gfc_create_var (gfc_int4_type_node, "stat");
    6722              : 
    6723              :       /* ERRMSG= only makes sense with STAT=.  */
    6724          290 :       if (code->expr2)
    6725              :         {
    6726           72 :           gfc_init_se (&se, NULL);
    6727           72 :           se.want_pointer = 1;
    6728           72 :           gfc_conv_expr_lhs (&se, code->expr2);
    6729           72 :           errmsg = se.expr;
    6730           72 :           errlen = se.string_length;
    6731              :         }
    6732              :       else
    6733              :         {
    6734          218 :           errmsg = null_pointer_node;
    6735          218 :           errlen = build_int_cst (gfc_charlen_type_node, 0);
    6736              :         }
    6737              : 
    6738              :       /* GOTO destinations.  */
    6739          290 :       label_errmsg = gfc_build_label_decl (NULL_TREE);
    6740          290 :       label_finish = gfc_build_label_decl (NULL_TREE);
    6741          290 :       TREE_USED (label_finish) = 0;
    6742              :     }
    6743              : 
    6744              :   /* When an expr3 is present evaluate it only once.  The standards prevent a
    6745              :      dependency of expr3 on the objects in the allocate list.  An expr3 can
    6746              :      be pre-evaluated in all cases.  One just has to make sure, to use the
    6747              :      correct way, i.e., to get the descriptor or to get a reference
    6748              :      expression.  */
    6749        14129 :   if (code->expr3)
    6750              :     {
    6751         3798 :       bool vtab_needed = false, temp_var_needed = false,
    6752         3798 :           temp_obj_created = false;
    6753              : 
    6754         3798 :       is_coarray = gfc_is_coarray (code->expr3);
    6755              : 
    6756          279 :       if (code->expr3->expr_type == EXPR_FUNCTION && !code->expr3->mold
    6757         4041 :           && (gfc_is_class_array_function (code->expr3)
    6758          213 :               || gfc_is_alloc_class_scalar_function (code->expr3)))
    6759           78 :         code->expr3->must_finalize = 1;
    6760              : 
    6761              :       /* Figure whether we need the vtab from expr3.  */
    6762         7608 :       for (al = code->ext.alloc.list; !vtab_needed && al != NULL;
    6763         3810 :            al = al->next)
    6764         3810 :         vtab_needed = (al->expr->ts.type == BT_CLASS);
    6765              : 
    6766         3798 :       gfc_init_se (&se, NULL);
    6767              :       /* When expr3 is a variable, i.e., a very simple expression, then
    6768              :          convert it once here.  If one has a source expression that has
    6769              :          substring references, part-refs, or %re/%im inquiries, wrap the
    6770              :          entity in parentheses to force evaluation of the expression.  */
    6771         3798 :       if (code->expr3->expr_type == EXPR_VARIABLE
    6772         3798 :           && is_subref_array (code->expr3))
    6773           60 :         code->expr3 = gfc_get_parentheses (code->expr3);
    6774              : 
    6775         3798 :       if (code->expr3->expr_type == EXPR_VARIABLE
    6776         2511 :           || code->expr3->expr_type == EXPR_ARRAY
    6777         1471 :           || code->expr3->expr_type == EXPR_CONSTANT)
    6778              :         {
    6779         2756 :           if (!code->expr3->mold
    6780          234 :               || code->expr3->ts.type == BT_CHARACTER
    6781          106 :               || vtab_needed
    6782           70 :               || code->ext.alloc.arr_spec_from_expr3)
    6783              :             {
    6784              :               /* Convert expr3 to a tree.  For all "simple" expression just
    6785              :                  get the descriptor or the reference, respectively, depending
    6786              :                  on the rank of the expr.  */
    6787         2756 :               if (code->ext.alloc.arr_spec_from_expr3 || code->expr3->rank != 0)
    6788         1598 :                 gfc_conv_expr_descriptor (&se, code->expr3);
    6789              :               else
    6790              :                 {
    6791         1158 :                   gfc_conv_expr_reference (&se, code->expr3);
    6792              : 
    6793              :                   /* gfc_conv_expr_reference wraps POINTER_PLUS_EXPR in a
    6794              :                      NOP_EXPR, which prevents gfortran from getting the vptr
    6795              :                      from the source=-expression.  Remove the NOP_EXPR and go
    6796              :                      with the POINTER_PLUS_EXPR in this case.  */
    6797         1158 :                   if (code->expr3->ts.type == BT_CLASS
    6798          256 :                       && TREE_CODE (se.expr) == NOP_EXPR
    6799         1314 :                       && (TREE_CODE (TREE_OPERAND (se.expr, 0))
    6800              :                                                             == POINTER_PLUS_EXPR
    6801          138 :                           || is_coarray))
    6802           30 :                     se.expr = TREE_OPERAND (se.expr, 0);
    6803              :                 }
    6804              :               /* Create a temp variable only for component refs to prevent
    6805              :                  having to go through the full deref-chain each time and to
    6806              :                  simplify computation of array properties.  */
    6807         2756 :               temp_var_needed = TREE_CODE (se.expr) == COMPONENT_REF;
    6808              :             }
    6809              :         }
    6810              :       else
    6811              :         {
    6812              :           /* In all other cases evaluate the expr3.  */
    6813         1042 :           symbol_attribute attr;
    6814              :           /* Get the descriptor for all arrays, that are not allocatable or
    6815              :              pointer, because the latter are descriptors already.
    6816              :              The exception are function calls returning a class object:
    6817              :              The descriptor is stored in their results _data component, which
    6818              :              is easier to access, when first a temporary variable for the
    6819              :              result is created and the descriptor retrieved from there.  */
    6820         1042 :           attr = gfc_expr_attr (code->expr3);
    6821         1042 :           if (code->expr3->rank != 0
    6822          248 :               && ((!attr.allocatable && !attr.pointer)
    6823           71 :                   || (code->expr3->expr_type == EXPR_FUNCTION
    6824           71 :                       && (code->expr3->ts.type != BT_CLASS
    6825           53 :                           || (code->expr3->value.function.isym
    6826           12 :                               && code->expr3->value.function.isym
    6827           12 :                                                          ->transformational)))))
    6828          207 :             gfc_conv_expr_descriptor (&se, code->expr3);
    6829              :           else
    6830          835 :             gfc_conv_expr_reference (&se, code->expr3);
    6831         1042 :           if (code->expr3->ts.type == BT_CLASS)
    6832          132 :             gfc_conv_class_to_class (&se, code->expr3,
    6833              :                                      code->expr3->ts,
    6834              :                                      false, true,
    6835              :                                      false, false);
    6836         1042 :           temp_obj_created = temp_var_needed = !VAR_P (se.expr);
    6837              :         }
    6838         3798 :       gfc_add_block_to_block (&block, &se.pre);
    6839         3798 :       if (code->expr3->must_finalize)
    6840              :         {
    6841           78 :           gfc_add_block_to_block (&final_block, &se.finalblock);
    6842           78 :           gfc_add_block_to_block (&final_block, &se.post);
    6843              :         }
    6844              :       else
    6845         3720 :         gfc_add_block_to_block (&post, &se.post);
    6846              : 
    6847              :       /* Special case when string in expr3 is scalar and has length zero.  */
    6848         3798 :       if (code->expr3->ts.type == BT_CHARACTER
    6849          845 :           && code->expr3->rank == 0
    6850         4294 :           && integer_zerop (se.string_length))
    6851              :         {
    6852            6 :           gfc_init_se (&se, NULL);
    6853            6 :           temp_var_needed = false;
    6854            6 :           expr3_len = build_zero_cst (gfc_charlen_type_node);
    6855            6 :           e3_is = E3_MOLD;
    6856              :         }
    6857              :       /* Prevent aliasing, i.e., se.expr may be already a
    6858              :              variable declaration.  */
    6859         3792 :       else if (se.expr != NULL_TREE && temp_var_needed)
    6860              :         {
    6861          908 :           tree var, desc;
    6862          908 :           tmp = (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr))
    6863          846 :                  || is_coarray
    6864          834 :                  || (code->expr3->ts.type == BT_CHARACTER
    6865          930 :                      && code->expr3->rank == 0)) ?
    6866              :                 se.expr
    6867          812 :               : build_fold_indirect_ref_loc (input_location, se.expr);
    6868              : 
    6869              :           /* Get the array descriptor and prepare it to be assigned to the
    6870              :              temporary variable var.  For classes the array descriptor is
    6871              :              in the _data component and the object goes into the
    6872              :              GFC_DECL_SAVED_DESCRIPTOR.  */
    6873          908 :           if (code->expr3->ts.type == BT_CLASS
    6874          187 :               && code->expr3->rank != 0)
    6875              :             {
    6876              :               /* When an array_ref was in expr3, then the descriptor is the
    6877              :                  first operand.  */
    6878           96 :               if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)) || is_coarray)
    6879              :                 {
    6880           49 :                   desc = TREE_OPERAND (tmp, 0);
    6881              :                 }
    6882              :               else
    6883              :                 {
    6884           47 :                   desc = tmp;
    6885           47 :                   tmp = gfc_class_data_get (tmp);
    6886              :                 }
    6887           96 :               if (code->ext.alloc.arr_spec_from_expr3)
    6888           39 :                 e3_is = E3_DESC;
    6889              :             }
    6890              :           else
    6891          824 :             desc = !is_coarray ? se.expr
    6892           12 :                                : TREE_OPERAND (TREE_OPERAND (se.expr, 0), 0);
    6893              :           /* We need a regular (non-UID) symbol here, therefore give a
    6894              :              prefix.  */
    6895          908 :           var = gfc_create_var (TREE_TYPE (tmp), "source");
    6896          908 :           if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)) || is_coarray)
    6897              :             {
    6898          121 :               gfc_allocate_lang_decl (var);
    6899          121 :               GFC_DECL_SAVED_DESCRIPTOR (var) = desc;
    6900              :             }
    6901          908 :           gfc_add_modify_loc (input_location, &block, var, tmp);
    6902              : 
    6903          908 :           expr3 = var;
    6904          908 :           if (se.string_length)
    6905              :             /* Evaluate it assuming that it also is complicated like expr3.  */
    6906           29 :             expr3_len = gfc_evaluate_now (se.string_length, &block);
    6907              :         }
    6908              :       else
    6909              :         {
    6910         2884 :           expr3 = se.expr;
    6911         2884 :           expr3_len = se.string_length;
    6912              :         }
    6913              : 
    6914              :       /* Deallocate any allocatable components in expressions that use a
    6915              :          temporary object, i.e. are not a simple alias of to an EXPR_VARIABLE.
    6916              :          E.g. temporaries of a function call need freeing of their components
    6917              :          here. Explicit derived type allocation of class entities uses expr3
    6918              :          to carry the default initializer. This must not be deallocated or
    6919              :          finalized.  */
    6920         3798 :       if ((code->expr3->ts.type == BT_DERIVED
    6921         2526 :            || code->expr3->ts.type == BT_CLASS)
    6922         1793 :           && (code->expr3->expr_type != EXPR_VARIABLE || temp_obj_created)
    6923         1205 :           && (code->expr3->ts.u.derived->attr.alloc_comp
    6924          903 :               || code->expr3->ts.u.derived->attr.pdt_type)
    6925          308 :           && !code->expr3->must_finalize
    6926          302 :           && !code->ext.alloc.expr3_not_explicit)
    6927              :         {
    6928          222 :           tmp = gfc_deallocate_alloc_comp (code->expr3->ts.u.derived,
    6929              :                                            expr3, code->expr3->rank);
    6930          222 :           gfc_prepend_expr_to_block (&post, tmp);
    6931              :         }
    6932              : 
    6933              :       /* Store what the expr3 is to be used for.  */
    6934         3798 :       if (e3_is == E3_UNSET)
    6935         6165 :         e3_is = expr3 != NULL_TREE ?
    6936         3753 :               (code->ext.alloc.arr_spec_from_expr3 ?
    6937              :                  E3_DESC
    6938         2586 :                : (code->expr3->mold ? E3_MOLD : E3_SOURCE))
    6939              :             : E3_UNSET;
    6940              : 
    6941              :       /* Figure how to get the _vtab entry.  This also obtains the tree
    6942              :          expression for accessing the _len component, because only
    6943              :          unlimited polymorphic objects, which are a subcategory of class
    6944              :          types, have a _len component.  */
    6945         3798 :       if (code->expr3->ts.type == BT_CLASS)
    6946              :         {
    6947          521 :           gfc_expr *rhs;
    6948          777 :           tmp = expr3 != NULL_TREE && POINTER_TYPE_P (TREE_TYPE (expr3)) ?
    6949          256 :                 build_fold_indirect_ref (expr3): expr3;
    6950              :           /* Polymorphic SOURCE: VPTR must be determined at run time.
    6951              :              expr3 may be a temporary array declaration, therefore check for
    6952              :              GFC_CLASS_TYPE_P before trying to get the _vptr component.  */
    6953          521 :           if (tmp != NULL_TREE
    6954          521 :               && (e3_is == E3_DESC
    6955          440 :                   || (GFC_CLASS_TYPE_P (TREE_TYPE (tmp))
    6956          280 :                       && (VAR_P (tmp) || !code->expr3->ref))
    6957          186 :                   || (VAR_P (tmp) && DECL_LANG_SPECIFIC (tmp))))
    6958          440 :             tmp = gfc_class_vptr_get (expr3);
    6959              :           else
    6960              :             {
    6961           81 :               rhs = gfc_find_and_cut_at_last_class_ref (code->expr3);
    6962           81 :               gfc_add_vptr_component (rhs);
    6963           81 :               gfc_init_se (&se, NULL);
    6964           81 :               se.want_pointer = 1;
    6965           81 :               gfc_conv_expr (&se, rhs);
    6966           81 :               tmp = se.expr;
    6967           81 :               gfc_free_expr (rhs);
    6968              :             }
    6969              :           /* Set the element size.  */
    6970          521 :           expr3_esize = gfc_vptr_size_get (tmp);
    6971          521 :           if (vtab_needed)
    6972          515 :             expr3_vptr = tmp;
    6973              :           /* Initialize the ref to the _len component.  */
    6974          521 :           if (expr3_len == NULL_TREE && UNLIMITED_POLY (code->expr3))
    6975              :             {
    6976              :               /* Same like for retrieving the _vptr.  */
    6977          164 :               if (expr3 != NULL_TREE && !code->expr3->ref)
    6978           92 :                 expr3_len = gfc_class_len_get (expr3);
    6979              :               else
    6980              :                 {
    6981           72 :                   rhs = gfc_find_and_cut_at_last_class_ref (code->expr3);
    6982           72 :                   gfc_add_len_component (rhs);
    6983           72 :                   gfc_init_se (&se, NULL);
    6984           72 :                   gfc_conv_expr (&se, rhs);
    6985           72 :                   expr3_len = se.expr;
    6986           72 :                   gfc_free_expr (rhs);
    6987              :                 }
    6988              :             }
    6989              :         }
    6990              :       else
    6991              :         {
    6992              :           /* When the object to allocate is polymorphic type, then it
    6993              :              needs its vtab set correctly, so deduce the required _vtab
    6994              :              and _len from the source expression.  */
    6995         3277 :           if (vtab_needed)
    6996              :             {
    6997              :               /* VPTR is fixed at compile time.  */
    6998         1194 :               gfc_symbol *vtab;
    6999              : 
    7000         1194 :               vtab = gfc_find_vtab (&code->expr3->ts);
    7001         1194 :               gcc_assert (vtab);
    7002         1194 :               expr3_vptr = gfc_get_symbol_decl (vtab);
    7003         1194 :               expr3_vptr = gfc_build_addr_expr (NULL_TREE,
    7004              :                                                 expr3_vptr);
    7005              :             }
    7006              :           /* _len component needs to be set, when ts is a character
    7007              :              array.  */
    7008         3277 :           if (expr3_len == NULL_TREE
    7009         2432 :               && code->expr3->ts.type == BT_CHARACTER)
    7010              :             {
    7011            0 :               if (code->expr3->ts.u.cl
    7012            0 :                   && code->expr3->ts.u.cl->length)
    7013              :                 {
    7014            0 :                   gfc_init_se (&se, NULL);
    7015            0 :                   gfc_conv_expr (&se, code->expr3->ts.u.cl->length);
    7016            0 :                   gfc_add_block_to_block (&block, &se.pre);
    7017            0 :                   expr3_len = gfc_evaluate_now (se.expr, &block);
    7018              :                 }
    7019            0 :               gcc_assert (expr3_len);
    7020              :             }
    7021              :           /* For character arrays only the kind's size is needed, because
    7022              :              the array mem_size is _len * (elem_size = kind_size).
    7023              :              For all other get the element size in the normal way.  */
    7024         3277 :           if (code->expr3->ts.type == BT_CHARACTER)
    7025          845 :             expr3_esize = TYPE_SIZE_UNIT (
    7026              :                   gfc_get_char_type (code->expr3->ts.kind));
    7027              :           else
    7028         2432 :             expr3_esize = TYPE_SIZE_UNIT (
    7029              :                   gfc_typenode_for_spec (&code->expr3->ts));
    7030              :         }
    7031         3798 :       gcc_assert (expr3_esize);
    7032         3798 :       expr3_esize = fold_convert (sizetype, expr3_esize);
    7033         3798 :       if (e3_is == E3_MOLD)
    7034              :         /* The expr3 is no longer valid after this point.  */
    7035          180 :         expr3 = NULL_TREE;
    7036              :     }
    7037        10331 :   else if (code->ext.alloc.ts.type != BT_UNKNOWN)
    7038              :     {
    7039              :       /* Compute the explicit typespec given only once for all objects
    7040              :          to allocate.  */
    7041         1250 :       if (code->ext.alloc.ts.type != BT_CHARACTER)
    7042          797 :         expr3_esize = TYPE_SIZE_UNIT (
    7043              :               gfc_typenode_for_spec (&code->ext.alloc.ts));
    7044          453 :       else if (code->ext.alloc.ts.u.cl->length != NULL)
    7045              :         {
    7046          447 :           gfc_expr *sz;
    7047          447 :           sz = gfc_copy_expr (code->ext.alloc.ts.u.cl->length);
    7048          447 :           gfc_init_se (&se_sz, NULL);
    7049          447 :           gfc_conv_expr (&se_sz, sz);
    7050          447 :           gfc_free_expr (sz);
    7051          447 :           ts_string_length = fold_convert (gfc_charlen_type_node, se_sz.expr);
    7052          447 :           tmp = gfc_get_char_type (code->ext.alloc.ts.kind);
    7053          447 :           tmp = TYPE_SIZE_UNIT (tmp);
    7054          447 :           tmp = fold_convert (TREE_TYPE (se_sz.expr), tmp);
    7055          447 :           gfc_add_block_to_block (&block, &se_sz.pre);
    7056          447 :           expr3_esize = fold_build2_loc (input_location, MULT_EXPR,
    7057          447 :                                          TREE_TYPE (se_sz.expr),
    7058              :                                          tmp, se_sz.expr);
    7059          447 :           expr3_esize = gfc_evaluate_now (expr3_esize, &block);
    7060              :         }
    7061              :       else
    7062              :         expr3_esize = NULL_TREE;
    7063              :     }
    7064              : 
    7065              :   /* The routine gfc_trans_assignment () already implements all
    7066              :      techniques needed.  Unfortunately we may have a temporary
    7067              :      variable for the source= expression here.  When that is the
    7068              :      case convert this variable into a temporary gfc_expr of type
    7069              :      EXPR_VARIABLE and used it as rhs for the assignment.  The
    7070              :      advantage is, that we get scalarizer support for free,
    7071              :      don't have to take care about scalar to array treatment and
    7072              :      will benefit of every enhancements gfc_trans_assignment ()
    7073              :      gets.
    7074              :      No need to check whether e3_is is E3_UNSET, because that is
    7075              :      done by expr3 != NULL_TREE.
    7076              :      Exclude variables since the following block does not handle
    7077              :      array sections.  In any case, there is no harm in sending
    7078              :      variables to gfc_trans_assignment because there is no
    7079              :      evaluation of variables.  */
    7080        14129 :   if (code->expr3)
    7081              :     {
    7082         3798 :       if (code->expr3->expr_type != EXPR_VARIABLE
    7083         2511 :           && e3_is != E3_MOLD && expr3 != NULL_TREE
    7084         6241 :           && DECL_P (expr3) && DECL_ARTIFICIAL (expr3))
    7085              :         {
    7086              :           /* Build a temporary symtree and symbol.  Do not add it to the current
    7087              :              namespace to prevent accidentaly modifying a colliding
    7088              :              symbol's as.  */
    7089         2048 :           newsym = XCNEW (gfc_symtree);
    7090              :           /* The name of the symtree should be unique, because gfc_create_var ()
    7091              :              took care about generating the identifier.  */
    7092         2048 :           newsym->name
    7093         2048 :             = gfc_get_string ("%s", IDENTIFIER_POINTER (DECL_NAME (expr3)));
    7094         2048 :           newsym->n.sym = gfc_new_symbol (newsym->name, NULL);
    7095              :           /* The backend_decl is known.  It is expr3, which is inserted
    7096              :              here.  */
    7097         2048 :           newsym->n.sym->backend_decl = expr3;
    7098         2048 :           e3rhs = gfc_get_expr ();
    7099         2048 :           e3rhs->rank = code->expr3->rank;
    7100         2048 :           e3rhs->corank = code->expr3->corank;
    7101         2048 :           e3rhs->symtree = newsym;
    7102              :           /* Mark the symbol referenced or gfc_trans_assignment will bug.  */
    7103         2048 :           newsym->n.sym->attr.referenced = 1;
    7104         2048 :           e3rhs->expr_type = EXPR_VARIABLE;
    7105         2048 :           e3rhs->where = code->expr3->where;
    7106              :           /* Set the symbols type, upto it was BT_UNKNOWN.  */
    7107         2048 :           if (IS_CLASS_ARRAY (code->expr3)
    7108           54 :               && code->expr3->expr_type == EXPR_FUNCTION
    7109           42 :               && code->expr3->value.function.isym
    7110           12 :               && code->expr3->value.function.isym->transformational)
    7111              :             {
    7112           12 :               e3rhs->ts = CLASS_DATA (code->expr3)->ts;
    7113              :             }
    7114         2036 :           else if (code->expr3->ts.type == BT_CLASS
    7115         2036 :                    && !GFC_CLASS_TYPE_P (TREE_TYPE (expr3)))
    7116           46 :             e3rhs->ts = CLASS_DATA (code->expr3)->ts;
    7117              :           else
    7118         1990 :             e3rhs->ts = code->expr3->ts;
    7119         2048 :           newsym->n.sym->ts = e3rhs->ts;
    7120              :           /* Check whether the expr3 is array valued.  */
    7121         2048 :           if (e3rhs->rank)
    7122              :             {
    7123         1281 :               gfc_array_spec *arr;
    7124         1281 :               arr = gfc_get_array_spec ();
    7125         1281 :               arr->rank = e3rhs->rank;
    7126         1281 :               arr->corank = e3rhs->corank;
    7127         1281 :               arr->type = AS_DEFERRED;
    7128              :               /* Set the dimension and pointer attribute for arrays
    7129              :                  to be on the safe side.  */
    7130         1281 :               newsym->n.sym->attr.dimension = 1;
    7131         1281 :               newsym->n.sym->attr.pointer = 1;
    7132         1281 :               newsym->n.sym->as = arr;
    7133         1281 :               if (IS_CLASS_ARRAY (code->expr3)
    7134           54 :                   && code->expr3->expr_type == EXPR_FUNCTION
    7135           42 :                   && code->expr3->value.function.isym
    7136           12 :                   && code->expr3->value.function.isym->transformational)
    7137              :                 {
    7138           12 :                   gfc_array_spec *tarr;
    7139           12 :                   tarr = gfc_get_array_spec ();
    7140           12 :                   *tarr = *arr;
    7141           12 :                   e3rhs->ts.u.derived->as = tarr;
    7142              :                 }
    7143         1281 :               gfc_add_full_array_ref (e3rhs, arr);
    7144              :             }
    7145          767 :           else if (POINTER_TYPE_P (TREE_TYPE (expr3)))
    7146           45 :             newsym->n.sym->attr.pointer = 1;
    7147              :           /* The string length is known, too.  Set it for char arrays.  */
    7148         2048 :           if (e3rhs->ts.type == BT_CHARACTER)
    7149          331 :             newsym->n.sym->ts.u.cl->backend_decl = expr3_len;
    7150         2048 :           gfc_commit_symbol (newsym->n.sym);
    7151              :         }
    7152              :       else
    7153         1750 :         e3rhs = gfc_copy_expr (code->expr3);
    7154              : 
    7155              :       // We need to propagate the bounds of the expr3 for source=/mold=.
    7156              :       // However, for non-named arrays, the lbound has to be 1 and neither the
    7157              :       // bound used inside the called function even when returning an
    7158              :       // allocatable/pointer nor the zero used internally.
    7159         3798 :       if (e3_is == E3_DESC
    7160         1206 :           && code->expr3->expr_type != EXPR_VARIABLE)
    7161        14129 :         e3_has_nodescriptor = true;
    7162              :     }
    7163              : 
    7164              :   /* Loop over all objects to allocate.  */
    7165        31222 :   for (al = code->ext.alloc.list; al != NULL; al = al->next)
    7166              :     {
    7167        17093 :       expr = gfc_copy_expr (al->expr);
    7168              :       /* UNLIMITED_POLY () needs the _data component to be set, when
    7169              :          expr is a unlimited polymorphic object.  But the _data component
    7170              :          has not been set yet, so check the derived type's attr for the
    7171              :          unlimited polymorphic flag to be safe.  */
    7172        17093 :       upoly_expr = UNLIMITED_POLY (expr)
    7173        33592 :                     || (expr->ts.type == BT_DERIVED
    7174         2622 :                         && expr->ts.u.derived->attr.unlimited_polymorphic);
    7175        17093 :       gfc_init_se (&se, NULL);
    7176              : 
    7177              :       /* For class types prepare the expressions to ref the _vptr
    7178              :          and the _len component.  The latter for unlimited polymorphic
    7179              :          types only.  */
    7180        17093 :       if (expr->ts.type == BT_CLASS)
    7181              :         {
    7182         3461 :           gfc_expr *expr_ref_vptr, *expr_ref_len;
    7183         3461 :           gfc_add_data_component (expr);
    7184              :           /* Prep the vptr handle.  */
    7185         3461 :           expr_ref_vptr = gfc_copy_expr (al->expr);
    7186         3461 :           gfc_add_vptr_component (expr_ref_vptr);
    7187         3461 :           se.want_pointer = 1;
    7188         3461 :           gfc_conv_expr (&se, expr_ref_vptr);
    7189         3461 :           al_vptr = se.expr;
    7190         3461 :           se.want_pointer = 0;
    7191         3461 :           gfc_free_expr (expr_ref_vptr);
    7192              :           /* Allocated unlimited polymorphic objects always have a _len
    7193              :              component.  */
    7194         3461 :           if (upoly_expr)
    7195              :             {
    7196          594 :               expr_ref_len = gfc_copy_expr (al->expr);
    7197          594 :               gfc_add_len_component (expr_ref_len);
    7198          594 :               gfc_conv_expr (&se, expr_ref_len);
    7199          594 :               al_len = se.expr;
    7200          594 :               gfc_free_expr (expr_ref_len);
    7201              :             }
    7202              :           else
    7203              :             /* In a loop ensure that all loop variable dependent variables
    7204              :                are initialized at the same spot in all execution paths.  */
    7205              :             al_len = NULL_TREE;
    7206              :         }
    7207              :       else
    7208              :         al_vptr = al_len = NULL_TREE;
    7209              : 
    7210        17093 :       se.want_pointer = 1;
    7211        17093 :       se.descriptor_only = 1;
    7212              : 
    7213        17093 :       gfc_conv_expr (&se, expr);
    7214        17093 :       if (expr->ts.type == BT_CHARACTER && expr->ts.deferred)
    7215              :         /* se.string_length now stores the .string_length variable of expr
    7216              :            needed to allocate character(len=:) arrays.  */
    7217         1084 :         al_len = se.string_length;
    7218              : 
    7219        17093 :       al_len_needs_set = al_len != NULL_TREE;
    7220              :       /* When allocating an array one cannot use much of the
    7221              :          pre-evaluated expr3 expressions, because for most of them the
    7222              :          scalarizer is needed which is not available in the pre-evaluation
    7223              :          step.  Therefore gfc_array_allocate () is responsible (and able)
    7224              :          to handle the complete array allocation.  Only the element size
    7225              :          needs to be provided, which is done most of the time by the
    7226              :          pre-evaluation step.  */
    7227        17093 :       if (expr3_len && (code->expr3->ts.type == BT_CHARACTER
    7228         1015 :                         || code->expr3->ts.type == BT_CLASS))
    7229              :         {
    7230              :           /* When al is an array, then the element size for each element
    7231              :              in the array is needed, which is the product of the len and
    7232              :              esize for char arrays.  For unlimited polymorphics len can be
    7233              :              zero, therefore take the maximum of len and one.  */
    7234         1015 :           tree lhs_len;
    7235              : 
    7236              :           /* If an allocatable character variable has fixed length, use it.
    7237              :              Otherwise use source length.  As different lengths are not
    7238              :              allowed by the standard, generate a runtime check.  */
    7239         1015 :           if (expr->ts.type == BT_CHARACTER && !expr->ts.deferred)
    7240              :             {
    7241          135 :               gfc_trans_same_strlen_check ("ALLOCATE with SOURCE= or MOLD=",
    7242              :                                            &code->expr3->where,
    7243              :                                            se.string_length, expr3_len,
    7244              :                                            &block);
    7245          135 :               lhs_len = fold_convert (TREE_TYPE (expr3_len), se.string_length);
    7246              :             }
    7247              :           else
    7248              :             lhs_len = expr3_len;
    7249              : 
    7250         2030 :           tmp = fold_build2_loc (input_location, MAX_EXPR,
    7251         1015 :                                  TREE_TYPE (expr3_len),
    7252         1015 :                                  lhs_len, fold_convert (TREE_TYPE (expr3_len),
    7253              :                                                         integer_one_node));
    7254         2030 :           tmp = fold_build2_loc (input_location, MULT_EXPR,
    7255         1015 :                                  TREE_TYPE (expr3_esize), expr3_esize,
    7256         1015 :                                  fold_convert (TREE_TYPE (expr3_esize), tmp));
    7257         1015 :         }
    7258              :       else
    7259              :         tmp = expr3_esize;
    7260              : 
    7261              :       /* Create runtime check for ALLOCATE of character with type-spec.  */
    7262        17093 :       if (expr->ts.type == BT_CHARACTER && !expr->ts.deferred
    7263          770 :           && ts_string_length
    7264           19 :           && se.string_length)
    7265           19 :         gfc_trans_same_strlen_check ("ALLOCATE with type-spec",
    7266           19 :                                      &al->expr->where,
    7267              :                                      ts_string_length, se.string_length,
    7268              :                                      &block);
    7269              : 
    7270        17093 :       gfc_omp_namelist *omp_alloc_item = NULL;
    7271        17093 :       if (omp_allocate)
    7272              :         {
    7273              :           gfc_omp_namelist *n = NULL;
    7274              :           gfc_omp_namelist *n_null = NULL;
    7275          130 :           for (n = omp_allocate; n; n = n->next)
    7276              :             {
    7277           88 :               if (n->sym == NULL)
    7278              :                 {
    7279           41 :                   n_null = n;
    7280           41 :                   continue;
    7281              :                 }
    7282           47 :               if (expr->expr_type == EXPR_VARIABLE
    7283           47 :                   && expr->symtree->n.sym == n->sym)
    7284              :                 {
    7285           25 :                   gfc_ref *ref;
    7286           38 :                   for (ref = expr->ref; ref; ref = ref->next)
    7287           16 :                     if (ref->type == REF_COMPONENT)
    7288              :                       break;
    7289              :                   if (ref == NULL)
    7290              :                     break;
    7291              :                 }
    7292              :             }
    7293           64 :           omp_alloc_item = n ? n : n_null;
    7294              : 
    7295              :         }
    7296              : 
    7297        17093 :       if (!gfc_array_allocate (&se, expr, stat, errmsg, errlen, label_finish,
    7298              :                                tmp, e3rhs ? e3rhs : code->expr3,
    7299              :                                e3_is == E3_DESC ? expr3 : NULL_TREE,
    7300              :                                e3_has_nodescriptor, omp_alloc_item,
    7301        17093 :                                code->ext.alloc.ts.type != BT_UNKNOWN))
    7302              :         {
    7303              :           /* A scalar or derived type.  First compute the size to
    7304              :              allocate.
    7305              : 
    7306              :              expr3_len is set when expr3 is an unlimited polymorphic
    7307              :              object or a deferred length string.
    7308              : 
    7309              :              If an allocatable character variable has fixed length, use it.
    7310              :              Otherwise use source length.  As different lengths are not
    7311              :              allowed by the standard, a runtime check was inserted
    7312              :              above.  */
    7313         5113 :           if (expr3_len != NULL_TREE)
    7314              :             {
    7315          539 :               tree lhs_len;
    7316          539 :               if (expr->ts.type == BT_CHARACTER && !expr->ts.deferred)
    7317           56 :                 lhs_len = fold_convert (TREE_TYPE (expr3_len),
    7318              :                                         se.string_length);
    7319              :               else
    7320              :                 lhs_len = expr3_len;
    7321              : 
    7322          539 :               tmp = fold_convert (TREE_TYPE (expr3_esize), lhs_len);
    7323          539 :               tmp = fold_build2_loc (input_location, MULT_EXPR,
    7324          539 :                                      TREE_TYPE (expr3_esize),
    7325              :                                       expr3_esize, tmp);
    7326          539 :               if (code->expr3->ts.type != BT_CLASS)
    7327              :                 /* expr3 is a deferred length string, i.e., we are
    7328              :                    done.  */
    7329              :                 memsz = tmp;
    7330              :               else
    7331              :                 {
    7332              :                   /* For unlimited polymorphic enties build
    7333              :                           (len > 0) ? element_size * len : element_size
    7334              :                      to compute the number of bytes to allocate.
    7335              :                      This allows the allocation of unlimited polymorphic
    7336              :                      objects from an expr3 that is also unlimited
    7337              :                      polymorphic and stores a _len dependent object,
    7338              :                      e.g., a string.  */
    7339           98 :                   memsz = fold_build2_loc (input_location, GT_EXPR,
    7340              :                                            logical_type_node, expr3_len,
    7341              :                                            build_zero_cst
    7342           98 :                                            (TREE_TYPE (expr3_len)));
    7343           98 :                   memsz = fold_build3_loc (input_location, COND_EXPR,
    7344           98 :                                          TREE_TYPE (expr3_esize),
    7345              :                                          memsz, tmp, expr3_esize);
    7346              :                 }
    7347              :             }
    7348         4574 :           else if (expr3_esize != NULL_TREE)
    7349              :             /* Any other object in expr3 just needs element size in
    7350              :                bytes.  */
    7351              :             memsz = expr3_esize;
    7352         2799 :           else if ((expr->ts.type == BT_CHARACTER && expr->ts.deferred)
    7353         2799 :                    || (upoly_expr
    7354            0 :                        && code->ext.alloc.ts.type == BT_CHARACTER))
    7355              :             {
    7356              :               /* Allocating deferred length char arrays need the length
    7357              :                  to allocate in the alloc_type_spec.  But also unlimited
    7358              :                  polymorphic objects may be allocated as char arrays.
    7359              :                  Both are handled here.  */
    7360            0 :               gfc_init_se (&se_sz, NULL);
    7361            0 :               gfc_conv_expr (&se_sz, code->ext.alloc.ts.u.cl->length);
    7362            0 :               gfc_add_block_to_block (&se.pre, &se_sz.pre);
    7363            0 :               se_sz.expr = gfc_evaluate_now (se_sz.expr, &se.pre);
    7364            0 :               gfc_add_block_to_block (&se.pre, &se_sz.post);
    7365            0 :               expr3_len = se_sz.expr;
    7366            0 :               tmp_expr3_len_flag = true;
    7367            0 :               tmp = TYPE_SIZE_UNIT (
    7368              :                     gfc_get_char_type (code->ext.alloc.ts.kind));
    7369            0 :               memsz = fold_build2_loc (input_location, MULT_EXPR,
    7370            0 :                                        TREE_TYPE (tmp),
    7371            0 :                                        fold_convert (TREE_TYPE (tmp),
    7372              :                                                      expr3_len),
    7373              :                                        tmp);
    7374              :             }
    7375         2799 :           else if (expr->ts.type == BT_CHARACTER)
    7376              :             {
    7377              :               /* Compute the number of bytes needed to allocate a fixed
    7378              :                  length char array.  */
    7379          170 :               gcc_assert (se.string_length != NULL_TREE);
    7380          170 :               tmp = TYPE_SIZE_UNIT (gfc_get_char_type (expr->ts.kind));
    7381          340 :               memsz = fold_build2_loc (input_location, MULT_EXPR,
    7382          170 :                                        TREE_TYPE (tmp), tmp,
    7383          170 :                                        fold_convert (TREE_TYPE (tmp),
    7384              :                                                      se.string_length));
    7385              :             }
    7386         2629 :           else if (code->ext.alloc.ts.type != BT_UNKNOWN)
    7387              :             /* Handle all types, where the alloc_type_spec is set.  */
    7388            0 :             memsz = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&code->ext.alloc.ts));
    7389              :           else
    7390              :             /* Handle size computation of the type declared to alloc.  */
    7391         2629 :             memsz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (se.expr)));
    7392              : 
    7393         5113 :           bool use_coarray_alloc
    7394         5113 :             = (flag_coarray == GFC_FCOARRAY_LIB
    7395         5113 :                && (caf_attr = gfc_caf_attr (expr, true, &caf_refs_comp))
    7396           77 :                                 .codimension);
    7397         5113 :           tree omp_cond = NULL_TREE;
    7398         5113 :           tree omp_alt_alloc = NULL_TREE;
    7399         5113 :           tree succ_add_expr = NULL_TREE;
    7400         5113 :           if (!use_coarray_alloc && omp_alloc_item)
    7401              :             {
    7402           28 :               tree align, alloc, sz;
    7403           28 :               gfc_se se2;
    7404              : 
    7405           28 :               omp_cond = boolean_true_node;
    7406           28 :               if (omp_alloc_item->u2.allocator)
    7407              :                 {
    7408            2 :                   gfc_init_se (&se2, NULL);
    7409            2 :                   gfc_conv_expr (&se2, omp_alloc_item->u2.allocator);
    7410            2 :                   gfc_add_block_to_block (&se.pre, &se2.pre);
    7411            2 :                   alloc = gfc_evaluate_now (se2.expr, &se.pre);
    7412            2 :                   gfc_add_block_to_block (&se.pre, &se2.post);
    7413              :                 }
    7414              :               else
    7415           26 :                 alloc = build_zero_cst (ptr_type_node);
    7416           28 :               tmp = TREE_TYPE (TREE_TYPE (se.expr));
    7417           28 :               if (tmp == void_type_node)
    7418            3 :                 tmp = gfc_typenode_for_spec (&expr->ts, 0);
    7419           28 :               if (omp_alloc_item->u.align)
    7420              :                 {
    7421           14 :                   gfc_init_se (&se2, NULL);
    7422           14 :                   gfc_conv_expr (&se2, omp_alloc_item->u.align);
    7423           14 :                   gcc_assert (CONSTANT_CLASS_P (se2.expr)
    7424              :                               && se2.pre.head == NULL
    7425              :                               && se2.post.head == NULL);
    7426           14 :                   align = build_int_cst (size_type_node,
    7427           14 :                                          MAX (tree_to_uhwi (se2.expr),
    7428              :                                          TYPE_ALIGN_UNIT (tmp)));
    7429              :                 }
    7430              :               else
    7431           14 :                 align = build_int_cst (size_type_node, TYPE_ALIGN_UNIT (tmp));
    7432           28 :               sz = fold_build2_loc (input_location, MAX_EXPR, size_type_node,
    7433              :                             fold_convert (size_type_node, memsz),
    7434              :                             build_int_cst (size_type_node, 1));
    7435           28 :               omp_alt_alloc = builtin_decl_explicit (BUILT_IN_GOMP_ALLOC);
    7436           28 :               DECL_ATTRIBUTES (omp_alt_alloc)
    7437           28 :                 = tree_cons (get_identifier ("omp allocator"),
    7438              :                              build_tree_list (NULL_TREE, alloc),
    7439           28 :                              DECL_ATTRIBUTES (omp_alt_alloc));
    7440           28 :               omp_alt_alloc = build_call_expr (omp_alt_alloc, 3, align, sz, alloc);
    7441           28 :               succ_add_expr = gfc_omp_call_add_alloc (se.expr);
    7442              :             }
    7443              : 
    7444              :           /* Store the caf-attributes for latter use.  */
    7445         5113 :           if (use_coarray_alloc)
    7446              :             {
    7447              :               /* Scalar allocatable components in coarray'ed derived types make
    7448              :                  it here and are treated now.  */
    7449           68 :               tree caf_decl, token;
    7450           68 :               gfc_se caf_se;
    7451              : 
    7452           68 :               is_coarray = true;
    7453              :               /* Set flag, to add synchronize after the allocate.  */
    7454          136 :               needs_caf_sync = needs_caf_sync
    7455           68 :                   || caf_attr.coarray_comp || !caf_refs_comp;
    7456              : 
    7457           68 :               gfc_init_se (&caf_se, NULL);
    7458              : 
    7459           68 :               caf_decl = gfc_get_tree_for_caf_expr (expr);
    7460           68 :               gfc_get_caf_token_offset (&caf_se, &token, NULL, caf_decl,
    7461              :                                         NULL_TREE, NULL);
    7462           68 :               gfc_add_block_to_block (&se.pre, &caf_se.pre);
    7463           68 :               gfc_allocate_allocatable (&se.pre, se.expr, memsz,
    7464              :                                         gfc_build_addr_expr (NULL_TREE, token),
    7465              :                                         NULL_TREE, NULL_TREE, NULL_TREE,
    7466              :                                         label_finish, expr, 1);
    7467              :             }
    7468              :           /* Allocate - for non-pointers with re-alloc checking.  */
    7469         5045 :           else if (gfc_expr_attr (expr).allocatable)
    7470         3480 :             gfc_allocate_allocatable (&se.pre, se.expr, memsz,
    7471              :                                       NULL_TREE, stat, errmsg, errlen,
    7472              :                                       label_finish, expr, 0,
    7473              :                                       omp_cond, omp_alt_alloc, succ_add_expr);
    7474              :           else
    7475         1565 :             gfc_allocate_using_malloc (&se.pre, se.expr, memsz, stat,
    7476              :                                       omp_cond, omp_alt_alloc, succ_add_expr);
    7477              :         }
    7478              :       else
    7479              :         {
    7480              :           /* Allocating coarrays needs a sync after the allocate executed.
    7481              :              Set the flag to add the sync after all objects are allocated.  */
    7482        11980 :           if (flag_coarray == GFC_FCOARRAY_LIB
    7483        11980 :               && (caf_attr = gfc_caf_attr (expr, true, &caf_refs_comp))
    7484          455 :                  .codimension)
    7485              :             {
    7486          393 :               is_coarray = true;
    7487          393 :               needs_caf_sync = needs_caf_sync
    7488          393 :                   || caf_attr.coarray_comp || !caf_refs_comp;
    7489              :             }
    7490              : 
    7491        11980 :           if (expr->ts.type == BT_CHARACTER && al_len != NULL_TREE
    7492         1079 :               && expr3_len != NULL_TREE)
    7493              :             {
    7494              :               /* Arrays need to have a _len set before the array
    7495              :                  descriptor is filled.  */
    7496          310 :               gfc_add_modify (&block, al_len,
    7497          310 :                               fold_convert (TREE_TYPE (al_len), expr3_len));
    7498              :               /* Prevent setting the length twice.  */
    7499          310 :               al_len_needs_set = false;
    7500              :             }
    7501        11670 :           else if (expr->ts.type == BT_CHARACTER && al_len != NULL_TREE
    7502          235 :               && code->ext.alloc.ts.u.cl->length)
    7503              :             {
    7504              :               /* Cover the cases where a string length is explicitly
    7505              :                  specified by a type spec for deferred length character
    7506              :                  arrays or unlimited polymorphic objects without a
    7507              :                  source= or mold= expression.  */
    7508          235 :               gfc_init_se (&se_sz, NULL);
    7509          235 :               gfc_conv_expr (&se_sz, code->ext.alloc.ts.u.cl->length);
    7510          235 :               gfc_add_block_to_block (&block, &se_sz.pre);
    7511          235 :               gfc_add_modify (&block, al_len,
    7512          235 :                               fold_convert (TREE_TYPE (al_len),
    7513              :                                             se_sz.expr));
    7514          235 :               al_len_needs_set = false;
    7515              :             }
    7516              :         }
    7517              : 
    7518        17093 :       gfc_add_block_to_block (&block, &se.pre);
    7519              : 
    7520              :       /* Error checking -- Note: ERRMSG only makes sense with STAT.  */
    7521        17093 :       if (code->expr1)
    7522              :         {
    7523          305 :           tmp = build1_v (GOTO_EXPR, label_errmsg);
    7524          305 :           parm = fold_build2_loc (input_location, NE_EXPR,
    7525              :                                   logical_type_node, stat,
    7526          305 :                                   build_int_cst (TREE_TYPE (stat), 0));
    7527          305 :           tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
    7528              :                                  gfc_unlikely (parm, PRED_FORTRAN_FAIL_ALLOC),
    7529              :                                  tmp, build_empty_stmt (input_location));
    7530          305 :           gfc_add_expr_to_block (&block, tmp);
    7531              :         }
    7532              : 
    7533              :       /* Set the vptr only when no source= is set.  When source= is set, then
    7534              :          the trans_assignment below will set the vptr.  */
    7535        17093 :       if (al_vptr != NULL_TREE && (!code->expr3 || code->expr3->mold))
    7536              :         {
    7537         1700 :           if (expr3_vptr != NULL_TREE)
    7538              :             /* The vtab is already known, so just assign it.  */
    7539           74 :             gfc_add_modify (&block, al_vptr,
    7540           74 :                             fold_convert (TREE_TYPE (al_vptr), expr3_vptr));
    7541              :           else
    7542              :             {
    7543              :               /* VPTR is fixed at compile time.  */
    7544         1626 :               gfc_symbol *vtab;
    7545         1626 :               gfc_typespec *ts;
    7546              : 
    7547         1626 :               if (code->expr3)
    7548              :                 /* Although expr3 is pre-evaluated above, it may happen,
    7549              :                    that for arrays or in mold= cases the pre-evaluation
    7550              :                    was not successful.  In these rare cases take the vtab
    7551              :                    from the typespec of expr3 here.  */
    7552            0 :                 ts = &code->expr3->ts;
    7553         1626 :               else if (code->ext.alloc.ts.type == BT_DERIVED || upoly_expr)
    7554              :                 /* The alloc_type_spec gives the type to allocate or the
    7555              :                    al is unlimited polymorphic, which enforces the use of
    7556              :                    an alloc_type_spec that is not necessarily a BT_DERIVED.  */
    7557          727 :                 ts = &code->ext.alloc.ts;
    7558              :               else
    7559              :                 /* Prepare for setting the vtab as declared.  */
    7560          899 :                 ts = &expr->ts;
    7561              : 
    7562         1626 :               vtab = gfc_find_vtab (ts);
    7563         1626 :               gcc_assert (vtab);
    7564         1626 :               tmp = gfc_build_addr_expr (NULL_TREE,
    7565              :                                          gfc_get_symbol_decl (vtab));
    7566         1626 :               gfc_add_modify (&block, al_vptr,
    7567         1626 :                               fold_convert (TREE_TYPE (al_vptr), tmp));
    7568              :             }
    7569              :         }
    7570              : 
    7571              :       /* Add assignment for string length.  */
    7572        17093 :       if (al_len != NULL_TREE && al_len_needs_set)
    7573              :         {
    7574         1133 :           if (expr3_len != NULL_TREE)
    7575              :             {
    7576          570 :               gfc_add_modify (&block, al_len,
    7577          570 :                               fold_convert (TREE_TYPE (al_len),
    7578              :                                             expr3_len));
    7579              :               /* When tmp_expr3_len_flag is set, then expr3_len is
    7580              :                  abused to carry the length information from the
    7581              :                  alloc_type.  Clear it to prevent setting incorrect len
    7582              :                  information in future loop iterations.  */
    7583          570 :               if (tmp_expr3_len_flag)
    7584              :                 /* No need to reset tmp_expr3_len_flag, because the
    7585              :                    presence of an expr3 cannot change within in the
    7586              :                    loop.  */
    7587          563 :                 expr3_len = NULL_TREE;
    7588              :             }
    7589          563 :           else if (code->ext.alloc.ts.type == BT_CHARACTER
    7590          227 :               && code->ext.alloc.ts.u.cl->length)
    7591              :             {
    7592              :               /* Cover the cases where a string length is explicitly
    7593              :                  specified by a type spec for deferred length character
    7594              :                  arrays or unlimited polymorphic objects without a
    7595              :                  source= or mold= expression.  */
    7596          227 :               if (expr3_esize == NULL_TREE || code->ext.alloc.ts.kind != 1)
    7597              :                 {
    7598           75 :                   gfc_init_se (&se_sz, NULL);
    7599           75 :                   gfc_conv_expr (&se_sz, code->ext.alloc.ts.u.cl->length);
    7600           75 :                   gfc_add_block_to_block (&block, &se_sz.pre);
    7601           75 :                   gfc_add_modify (&block, al_len,
    7602           75 :                                   fold_convert (TREE_TYPE (al_len),
    7603              :                                                 se_sz.expr));
    7604              :                 }
    7605              :               else
    7606          152 :                 gfc_add_modify (&block, al_len,
    7607          152 :                                 fold_convert (TREE_TYPE (al_len),
    7608              :                                               expr3_esize));
    7609              :             }
    7610              :           else
    7611              :             /* No length information needed, because type to allocate
    7612              :                has no length.  Set _len to 0.  */
    7613          336 :             gfc_add_modify (&block, al_len,
    7614          336 :                             fold_convert (TREE_TYPE (al_len),
    7615              :                                           integer_zero_node));
    7616              :         }
    7617              : 
    7618        17093 :       init_expr = NULL;
    7619        17093 :       if (code->expr3 && !code->expr3->mold && e3_is != E3_MOLD)
    7620              :         {
    7621              :           /* Initialization via SOURCE block (or static default initializer).
    7622              :              Switch off automatic reallocation since we have just done the
    7623              :              ALLOCATE.  */
    7624         3634 :           int realloc_lhs = flag_realloc_lhs;
    7625         3634 :           gfc_expr *init_expr = gfc_expr_to_initialize (expr);
    7626         3634 :           gfc_expr *rhs = e3rhs ? e3rhs : gfc_copy_expr (code->expr3);
    7627         3634 :           flag_realloc_lhs = 0;
    7628              : 
    7629              :           /* The handling of code->expr3 above produces a derived type of
    7630              :              type "STAR", whose size defaults to size(void*). In order to
    7631              :              have the right type information for the assignment, we must
    7632              :              reconstruct an unlimited polymorphic rhs.  */
    7633         3634 :           if (UNLIMITED_POLY (code->expr3)
    7634          151 :               && e3rhs && e3rhs->ts.type == BT_DERIVED
    7635            6 :               && !strcmp (e3rhs->ts.u.derived->name, "STAR"))
    7636              :             {
    7637            6 :               gfc_ref *ref;
    7638            6 :               gcc_assert (TREE_CODE (expr3_vptr) == COMPONENT_REF);
    7639            6 :               tmp = gfc_create_var (gfc_typenode_for_spec (&code->expr3->ts),
    7640              :                                     "e3");
    7641            6 :               gfc_add_modify (&block, tmp,
    7642              :                               gfc_get_class_from_expr (expr3_vptr));
    7643            6 :               rhs->symtree->n.sym->backend_decl = tmp;
    7644            6 :               rhs->ts = code->expr3->ts;
    7645            6 :               rhs->symtree->n.sym->ts = rhs->ts;
    7646            6 :               for (ref = init_expr->ref; ref; ref = ref->next)
    7647              :                 {
    7648              :                   /* Copy over the lhs _data component ref followed by the
    7649              :                      full array reference for source expressions with rank.
    7650              :                      Otherwise, just copy the _data component ref.  */
    7651            6 :                   if (code->expr3->rank
    7652            6 :                       && ref && ref->next && !ref->next->next)
    7653              :                     {
    7654            6 :                       rhs->ref = gfc_copy_ref (ref);
    7655            6 :                       break;
    7656              :                     }
    7657            0 :                   else if ((init_expr->rank && !code->expr3->rank
    7658            0 :                             && ref && ref->next && !ref->next->next)
    7659            0 :                            || (ref && !ref->next))
    7660              :                     {
    7661            0 :                       rhs->ref = gfc_copy_ref (ref);
    7662            0 :                       gfc_free_ref_list (rhs->ref->next);
    7663            0 :                       rhs->ref->next = NULL;
    7664            0 :                       break;
    7665              :                     }
    7666              :                 }
    7667              :             }
    7668              : 
    7669              :           /* Set the symbol to be artificial so that the result is not finalized.  */
    7670         3634 :           init_expr->symtree->n.sym->attr.artificial = 1;
    7671         3634 :           tmp = gfc_trans_assignment (init_expr, rhs, true, false, true,
    7672              :                                       false);
    7673         3634 :           init_expr->symtree->n.sym->attr.artificial = 0;
    7674              : 
    7675         3634 :           flag_realloc_lhs = realloc_lhs;
    7676              :           /* Free the expression allocated for init_expr.  */
    7677         3634 :           gfc_free_expr (init_expr);
    7678         3634 :           if (rhs != e3rhs)
    7679            0 :             gfc_free_expr (rhs);
    7680         3634 :           gfc_add_expr_to_block (&block, tmp);
    7681         3634 :         }
    7682              :       /* Set KIND and LEN PDT components and allocate those that are
    7683              :          parameterized.  */
    7684        13459 :       else if (IS_PDT (expr))
    7685              :         {
    7686           98 :           if (code->expr3 && code->expr3->param_list)
    7687              :             param_list = code->expr3->param_list;
    7688           98 :           else if (expr->param_list)
    7689              :             param_list = expr->param_list;
    7690              :           else
    7691           28 :             param_list = expr->symtree->n.sym->param_list;
    7692           98 :           tmp = gfc_allocate_pdt_comp (expr->ts.u.derived, se.expr,
    7693              :                                        expr->rank, param_list);
    7694           98 :           gfc_add_expr_to_block (&block, tmp);
    7695              :         }
    7696              :       /* Ditto for CLASS expressions.  */
    7697        13361 :       else if (IS_CLASS_PDT (expr))
    7698              :         {
    7699            0 :           if (code->expr3 && code->expr3->param_list)
    7700              :             param_list = code->expr3->param_list;
    7701            0 :           else if (expr->param_list)
    7702              :             param_list = expr->param_list;
    7703              :           else
    7704            0 :             param_list = expr->symtree->n.sym->param_list;
    7705            0 :           tmp = gfc_allocate_pdt_comp (CLASS_DATA (expr)->ts.u.derived,
    7706              :                                        se.expr, expr->rank, param_list);
    7707            0 :           gfc_add_expr_to_block (&block, tmp);
    7708              :         }
    7709        13361 :       else if (code->expr3 && code->expr3->mold
    7710          296 :                && code->expr3->ts.type == BT_CLASS)
    7711              :         {
    7712              :           /* Use class_init_assign to initialize expr.  */
    7713           61 :           gfc_code *ini;
    7714           61 :           ini = gfc_get_code (EXEC_ALLOCATE);
    7715           61 :           ini->expr1 = gfc_find_and_cut_at_last_class_ref (expr, true);
    7716           61 :           tmp = gfc_trans_class_init_assign (ini);
    7717           61 :           gfc_free_statements (ini);
    7718           61 :           if (tmp != NULL_TREE)
    7719           61 :             gfc_add_expr_to_block (&block, tmp);
    7720              :         }
    7721        13300 :       else if ((init_expr = allocate_get_initializer (code, expr)))
    7722              :         {
    7723              :           /* Use class_init_assign to initialize expr.  */
    7724         2017 :           gfc_code *ini;
    7725         2017 :           int realloc_lhs = flag_realloc_lhs;
    7726         2017 :           ini = gfc_get_code (EXEC_INIT_ASSIGN);
    7727         2017 :           ini->expr1 = gfc_expr_to_initialize (expr);
    7728         2017 :           ini->expr2 = init_expr;
    7729         2017 :           flag_realloc_lhs = 0;
    7730         2017 :           tmp= gfc_trans_init_assign (ini);
    7731         2017 :           flag_realloc_lhs = realloc_lhs;
    7732         2017 :           gfc_free_statements (ini);
    7733              :           /* Init_expr is freeed by above free_statements, just need to null
    7734              :              it here.  */
    7735         2017 :           init_expr = NULL;
    7736         2017 :           gfc_add_expr_to_block (&block, tmp);
    7737              :         }
    7738              : 
    7739              :       /* Nullify all pointers in derived type coarrays.  This registers a
    7740              :          token for them which allows their allocation.  */
    7741        17093 :       if (is_coarray)
    7742              :         {
    7743          509 :           gfc_symbol *type = NULL;
    7744          509 :           symbol_attribute caf_attr;
    7745          509 :           int rank = 0;
    7746          509 :           if (code->ext.alloc.ts.type == BT_DERIVED
    7747           10 :               && code->ext.alloc.ts.u.derived->attr.pointer_comp)
    7748              :             {
    7749            0 :               type = code->ext.alloc.ts.u.derived;
    7750            0 :               rank = type->attr.dimension ? type->as->rank : 0;
    7751            0 :               gfc_clear_attr (&caf_attr);
    7752              :             }
    7753          509 :           else if (expr->ts.type == BT_DERIVED
    7754          114 :                    && expr->ts.u.derived->attr.pointer_comp)
    7755              :             {
    7756           16 :               type = expr->ts.u.derived;
    7757           16 :               rank = expr->rank;
    7758           16 :               caf_attr = gfc_caf_attr (expr, true);
    7759              :             }
    7760              : 
    7761              :           /* Initialize the tokens of pointer components in derived type
    7762              :              coarrays.  */
    7763           16 :           if (type)
    7764              :             {
    7765           20 :               tmp = (caf_attr.codimension && !caf_attr.dimension)
    7766           20 :                   ? gfc_conv_descriptor_data_get (se.expr) : se.expr;
    7767           16 :               tmp = gfc_nullify_alloc_comp (type, tmp, rank,
    7768              :                                             GFC_STRUCTURE_CAF_MODE_IN_COARRAY);
    7769           16 :               gfc_add_expr_to_block (&block, tmp);
    7770              :             }
    7771              :         }
    7772              : 
    7773        17093 :       gfc_free_expr (expr);
    7774              :     } // for-loop
    7775              : 
    7776        14129 :   if (e3rhs)
    7777              :     {
    7778         3798 :       if (newsym)
    7779              :         {
    7780         2048 :           gfc_free_symbol (newsym->n.sym);
    7781         2048 :           XDELETE (newsym);
    7782              :         }
    7783         3798 :       gfc_free_expr (e3rhs);
    7784              :     }
    7785              :   /* STAT.  */
    7786        14129 :   if (code->expr1)
    7787              :     {
    7788          290 :       tmp = build1_v (LABEL_EXPR, label_errmsg);
    7789          290 :       gfc_add_expr_to_block (&block, tmp);
    7790              :     }
    7791              : 
    7792              :   /* ERRMSG - only useful if STAT is present.  */
    7793        14129 :   if (code->expr1 && code->expr2)
    7794              :     {
    7795           72 :       const char *msg = "Attempt to allocate an allocated object";
    7796           72 :       const char *oommsg = "Insufficient virtual memory";
    7797           72 :       tree slen, dlen, errmsg_str, oom_str, oom_loc;
    7798           72 :       stmtblock_t errmsg_block;
    7799              : 
    7800           72 :       gfc_init_block (&errmsg_block);
    7801              : 
    7802           72 :       errmsg_str = gfc_create_var (pchar_type_node, "ERRMSG");
    7803           72 :       gfc_add_modify (&errmsg_block, errmsg_str,
    7804              :                 gfc_build_addr_expr (pchar_type_node,
    7805              :                         gfc_build_localized_cstring_const (msg)));
    7806              : 
    7807           72 :       slen = build_int_cst (gfc_charlen_type_node, strlen (msg));
    7808           72 :       dlen = gfc_get_expr_charlen (code->expr2);
    7809           72 :       slen = fold_build2_loc (input_location, MIN_EXPR,
    7810           72 :                               TREE_TYPE (slen), dlen, slen);
    7811              : 
    7812           72 :       gfc_trans_string_copy (&errmsg_block, dlen, errmsg,
    7813           72 :                              code->expr2->ts.kind,
    7814              :                              slen, errmsg_str,
    7815              :                              gfc_default_character_kind);
    7816           72 :       dlen = gfc_finish_block (&errmsg_block);
    7817              : 
    7818           72 :       tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
    7819           72 :                              stat, build_int_cst (TREE_TYPE (stat),
    7820              :                                                   LIBERROR_ALLOCATION));
    7821              : 
    7822           72 :       tmp = build3_v (COND_EXPR, tmp,
    7823              :                       dlen, build_empty_stmt (input_location));
    7824              : 
    7825           72 :       gfc_add_expr_to_block (&block, tmp);
    7826              : 
    7827           72 :       oom_str = gfc_create_var (pchar_type_node, "OOMMSG");
    7828           72 :       oom_loc = gfc_build_localized_cstring_const (oommsg);
    7829           72 :       gfc_add_modify (&errmsg_block, oom_str,
    7830              :                       gfc_build_addr_expr (pchar_type_node, oom_loc));
    7831              : 
    7832           72 :       slen = build_int_cst (gfc_charlen_type_node, strlen (oommsg));
    7833           72 :       dlen = gfc_get_expr_charlen (code->expr2);
    7834           72 :       slen = fold_build2_loc (input_location, MIN_EXPR,
    7835           72 :                               TREE_TYPE (slen), dlen, slen);
    7836              : 
    7837           72 :       gfc_trans_string_copy (&errmsg_block, dlen, errmsg,
    7838           72 :                              code->expr2->ts.kind,
    7839              :                              slen, oom_str,
    7840              :                              gfc_default_character_kind);
    7841           72 :       dlen = gfc_finish_block (&errmsg_block);
    7842              : 
    7843           72 :       tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
    7844           72 :                              stat, build_int_cst (TREE_TYPE (stat),
    7845              :                                                   LIBERROR_NO_MEMORY));
    7846              : 
    7847           72 :       tmp = build3_v (COND_EXPR, tmp,
    7848              :                       dlen, build_empty_stmt (input_location));
    7849              : 
    7850           72 :       gfc_add_expr_to_block (&block, tmp);
    7851              :     }
    7852              : 
    7853              :   /* STAT block.  */
    7854        14129 :   if (code->expr1)
    7855              :     {
    7856          290 :       if (TREE_USED (label_finish))
    7857              :         {
    7858           16 :           tmp = build1_v (LABEL_EXPR, label_finish);
    7859           16 :           gfc_add_expr_to_block (&block, tmp);
    7860              :         }
    7861              : 
    7862          290 :       gfc_init_se (&se, NULL);
    7863          290 :       gfc_conv_expr_lhs (&se, code->expr1);
    7864          290 :       tmp = convert (TREE_TYPE (se.expr), stat);
    7865          290 :       gfc_add_modify (&block, se.expr, tmp);
    7866              :     }
    7867              : 
    7868        14129 :   if (needs_caf_sync)
    7869              :     {
    7870              :       /* Add a sync all after the allocation has been executed.  */
    7871          226 :       tree zero_size = build_zero_cst (size_type_node);
    7872          226 :       tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
    7873              :                                  3, null_pointer_node, null_pointer_node,
    7874              :                                  zero_size);
    7875          226 :       gfc_add_expr_to_block (&post, tmp);
    7876              :     }
    7877              : 
    7878        14129 :   gfc_add_block_to_block (&block, &se.post);
    7879        14129 :   gfc_add_block_to_block (&block, &post);
    7880        14129 :   if (code->expr3 && code->expr3->must_finalize)
    7881           78 :     gfc_add_block_to_block (&block, &final_block);
    7882              : 
    7883        14129 :   return gfc_finish_block (&block);
    7884              : }
    7885              : 
    7886              : 
    7887              : /* Translate a DEALLOCATE statement.  */
    7888              : 
    7889              : tree
    7890         8623 : gfc_trans_deallocate (gfc_code *code)
    7891              : {
    7892         8623 :   gfc_se se;
    7893         8623 :   gfc_alloc *al;
    7894         8623 :   tree apstat, pstat, stat, errmsg, errlen, tmp;
    7895         8623 :   tree label_finish, label_errmsg;
    7896         8623 :   stmtblock_t block;
    7897              : 
    7898         8623 :   pstat = apstat = stat = errmsg = errlen = tmp = NULL_TREE;
    7899         8623 :   label_finish = label_errmsg = NULL_TREE;
    7900              : 
    7901         8623 :   gfc_start_block (&block);
    7902              : 
    7903              :   /* Count the number of failed deallocations.  If deallocate() was
    7904              :      called with STAT= , then set STAT to the count.  If deallocate
    7905              :      was called with ERRMSG, then set ERRMG to a string.  */
    7906         8623 :   if (code->expr1)
    7907              :     {
    7908         2604 :       tree gfc_int4_type_node = gfc_get_int_type (4);
    7909              : 
    7910         2604 :       stat = gfc_create_var (gfc_int4_type_node, "stat");
    7911         2604 :       pstat = gfc_build_addr_expr (NULL_TREE, stat);
    7912              : 
    7913              :       /* GOTO destinations.  */
    7914         2604 :       label_errmsg = gfc_build_label_decl (NULL_TREE);
    7915         2604 :       label_finish = gfc_build_label_decl (NULL_TREE);
    7916         2604 :       TREE_USED (label_finish) = 0;
    7917              :     }
    7918              : 
    7919              :   /* Set ERRMSG - only needed if STAT is available.  */
    7920         8623 :   if (code->expr1 && code->expr2)
    7921              :     {
    7922           51 :       gfc_init_se (&se, NULL);
    7923           51 :       se.want_pointer = 1;
    7924           51 :       gfc_conv_expr_lhs (&se, code->expr2);
    7925           51 :       errmsg = se.expr;
    7926           51 :       errlen = se.string_length;
    7927              :     }
    7928              : 
    7929        19486 :   for (al = code->ext.alloc.list; al != NULL; al = al->next)
    7930              :     {
    7931        10863 :       gfc_expr *expr = gfc_copy_expr (al->expr);
    7932        10863 :       bool is_coarray = false, is_coarray_array = false;
    7933        10863 :       int caf_mode = 0;
    7934        10863 :       gfc_ref * ref;
    7935        10863 :       gfc_actual_arglist * param_list;
    7936              : 
    7937        10863 :       gcc_assert (expr->expr_type == EXPR_VARIABLE);
    7938              : 
    7939        10863 :       if (expr->ts.type == BT_CLASS)
    7940         2006 :         gfc_add_data_component (expr);
    7941              : 
    7942        10863 :       gfc_init_se (&se, NULL);
    7943        10863 :       gfc_start_block (&se.pre);
    7944              : 
    7945        10863 :       se.want_pointer = 1;
    7946        10863 :       se.descriptor_only = 1;
    7947        10863 :       gfc_conv_expr (&se, expr);
    7948              : 
    7949              :       /* Deallocate PDT components that are parameterized.  */
    7950        10863 :       tmp = NULL;
    7951        10863 :       param_list = expr->param_list;
    7952        10863 :       if (!param_list && expr->symtree->n.sym->param_list)
    7953              :         param_list = expr->symtree->n.sym->param_list;
    7954        25849 :       for (ref = expr->ref; ref; ref = ref->next)
    7955        14986 :         if (ref->type ==  REF_COMPONENT
    7956         6839 :             && IS_PDT (ref->u.c.component)
    7957           83 :             && ref->u.c.component->param_list)
    7958        14986 :           param_list = ref->u.c.component->param_list;
    7959        10863 :       if (expr->ts.type == BT_DERIVED
    7960         2809 :           && ((expr->ts.u.derived->attr.pdt_type && param_list)
    7961         2685 :               || expr->ts.u.derived->attr.pdt_comp))
    7962          124 :         tmp = gfc_deallocate_pdt_comp (expr->ts.u.derived, se.expr, expr->rank);
    7963        10739 :       else if (IS_CLASS_PDT (expr) && expr->symtree->n.sym->param_list)
    7964            0 :         tmp = gfc_deallocate_pdt_comp (CLASS_DATA (expr)->ts.u.derived,
    7965              :                                        se.expr, expr->rank);
    7966              : 
    7967          124 :       if (tmp)
    7968           48 :         gfc_add_expr_to_block (&se.pre, tmp);
    7969              : 
    7970        10863 :       if (flag_coarray == GFC_FCOARRAY_LIB
    7971        10863 :           || flag_coarray == GFC_FCOARRAY_SINGLE)
    7972              :         {
    7973          434 :           bool comp_ref;
    7974          434 :           symbol_attribute caf_attr = gfc_caf_attr (expr, false, &comp_ref);
    7975          434 :           if (caf_attr.codimension)
    7976              :             {
    7977          317 :               is_coarray = true;
    7978          145 :               is_coarray_array = caf_attr.dimension || !comp_ref
    7979          377 :                   || caf_attr.coarray_comp;
    7980              : 
    7981          317 :               if (flag_coarray == GFC_FCOARRAY_LIB)
    7982              :                 /* When the expression to deallocate is referencing a
    7983              :                    component, then only deallocate it, but do not
    7984              :                    deregister.  */
    7985           98 :                 caf_mode = GFC_STRUCTURE_CAF_MODE_IN_COARRAY
    7986          210 :                     | (comp_ref && !caf_attr.coarray_comp
    7987              :                        ? GFC_STRUCTURE_CAF_MODE_DEALLOC_ONLY : 0);
    7988              :             }
    7989              :         }
    7990              : 
    7991        10863 :       if (expr->rank || is_coarray_array)
    7992              :         {
    7993         7497 :           gfc_ref *ref;
    7994              : 
    7995         6219 :           if (gfc_bt_struct (expr->ts.type)
    7996         1278 :               && expr->ts.u.derived->attr.alloc_comp
    7997         8139 :               && !gfc_is_finalizable (expr->ts.u.derived, NULL))
    7998              :             {
    7999          638 :               gfc_ref *last = NULL;
    8000              : 
    8001         1776 :               for (ref = expr->ref; ref; ref = ref->next)
    8002         1138 :                 if (ref->type == REF_COMPONENT)
    8003          430 :                   last = ref;
    8004              : 
    8005              :               /* Do not deallocate the components of a derived type
    8006              :                  ultimate pointer component.  */
    8007          638 :               if (!(last && last->u.c.component->attr.pointer)
    8008          257 :                     && !(!last && expr->symtree->n.sym->attr.pointer))
    8009              :                 {
    8010           30 :                   if (is_coarray && expr->rank == 0
    8011           21 :                       && (!last || !last->u.c.component->attr.dimension)
    8012          635 :                       && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr)))
    8013              :                     {
    8014              :                       /* Add the ref to the data member only, when this is not
    8015              :                          a regular array or deallocate_alloc_comp will try to
    8016              :                          add another one.  */
    8017           21 :                       tmp = gfc_conv_descriptor_data_get (se.expr);
    8018              :                     }
    8019              :                   else
    8020          593 :                     tmp = se.expr;
    8021          614 :                   tmp = gfc_deallocate_alloc_comp (expr->ts.u.derived, tmp,
    8022              :                                                    expr->rank, caf_mode);
    8023          614 :                   gfc_add_expr_to_block (&se.pre, tmp);
    8024              :                 }
    8025              :             }
    8026              : 
    8027         7497 :           if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr)))
    8028              :             {
    8029         7438 :               gfc_coarray_deregtype caf_dtype;
    8030              : 
    8031         7438 :               if (is_coarray)
    8032          476 :                 caf_dtype = gfc_caf_is_dealloc_only (caf_mode)
    8033          274 :                     ? GFC_CAF_COARRAY_DEALLOCATE_ONLY
    8034              :                     : GFC_CAF_COARRAY_DEREGISTER;
    8035              :               else
    8036              :                 caf_dtype = GFC_CAF_COARRAY_NOCOARRAY;
    8037         7438 :               tmp = gfc_deallocate_with_status (se.expr, pstat, errmsg, errlen,
    8038              :                                                 label_finish, false, expr,
    8039              :                                                 caf_dtype);
    8040         7438 :               gfc_add_expr_to_block (&se.pre, tmp);
    8041              :             }
    8042           59 :           else if (TREE_CODE (se.expr) == COMPONENT_REF
    8043           59 :                    && TREE_CODE (TREE_TYPE (se.expr)) == ARRAY_TYPE
    8044          118 :                    && TREE_CODE (TREE_TYPE (TREE_TYPE (se.expr)))
    8045              :                         == RECORD_TYPE)
    8046              :             {
    8047              :               /* class.cc(finalize_component) generates these, when a
    8048              :                  finalizable entity has a non-allocatable derived type array
    8049              :                  component, which has allocatable components. Obtain the
    8050              :                  derived type of the array and deallocate the allocatable
    8051              :                  components. */
    8052           65 :               for (ref = expr->ref; ref; ref = ref->next)
    8053              :                 {
    8054           65 :                   if (ref->u.c.component->attr.dimension
    8055           59 :                       && ref->u.c.component->ts.type == BT_DERIVED)
    8056              :                     break;
    8057              :                 }
    8058              : 
    8059           59 :               if (ref && ref->u.c.component->ts.u.derived->attr.alloc_comp
    8060          118 :                   && !gfc_is_finalizable (ref->u.c.component->ts.u.derived,
    8061              :                                           NULL))
    8062              :                 {
    8063           59 :                   tmp = gfc_deallocate_alloc_comp
    8064           59 :                                 (ref->u.c.component->ts.u.derived,
    8065              :                                  se.expr, expr->rank);
    8066           59 :                   gfc_add_expr_to_block (&se.pre, tmp);
    8067              :                 }
    8068              :             }
    8069              : 
    8070         7497 :           if (al->expr->ts.type == BT_CLASS)
    8071              :             {
    8072         1131 :               gfc_reset_vptr (&se.pre, al->expr);
    8073         1131 :               if (UNLIMITED_POLY (al->expr)
    8074          736 :                   || (al->expr->ts.type == BT_DERIVED
    8075            0 :                       && al->expr->ts.u.derived->attr.unlimited_polymorphic))
    8076              :                 /* Clear _len, too.  */
    8077          395 :                 gfc_reset_len (&se.pre, al->expr);
    8078              :             }
    8079              :         }
    8080              :       else
    8081              :         {
    8082         6732 :           tmp = gfc_deallocate_scalar_with_status (se.expr, pstat, label_finish,
    8083              :                                                    false, al->expr,
    8084         3366 :                                                    al->expr->ts, NULL_TREE,
    8085              :                                                    is_coarray);
    8086         3366 :           gfc_add_expr_to_block (&se.pre, tmp);
    8087              : 
    8088              :           /* Set to zero after deallocation.  */
    8089         3366 :           tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
    8090              :                                  se.expr,
    8091         3366 :                                  build_int_cst (TREE_TYPE (se.expr), 0));
    8092         3366 :           gfc_add_expr_to_block (&se.pre, tmp);
    8093              : 
    8094         3366 :           if (al->expr->ts.type == BT_CLASS)
    8095              :             {
    8096          875 :               gfc_reset_vptr (&se.pre, al->expr);
    8097          875 :               if (UNLIMITED_POLY (al->expr)
    8098          643 :                   || (al->expr->ts.type == BT_DERIVED
    8099            0 :                       && al->expr->ts.u.derived->attr.unlimited_polymorphic))
    8100              :                 /* Clear _len, too.  */
    8101          232 :                 gfc_reset_len (&se.pre, al->expr);
    8102              :             }
    8103              :         }
    8104              : 
    8105        10863 :       if (code->expr1)
    8106              :         {
    8107         2643 :           tree cond;
    8108              : 
    8109         2643 :           cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, stat,
    8110         2643 :                                   build_int_cst (TREE_TYPE (stat), 0));
    8111         2643 :           tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
    8112              :                                  gfc_unlikely (cond, PRED_FORTRAN_FAIL_ALLOC),
    8113              :                                  build1_v (GOTO_EXPR, label_errmsg),
    8114              :                                  build_empty_stmt (input_location));
    8115         2643 :           gfc_add_expr_to_block (&se.pre, tmp);
    8116              :         }
    8117              : 
    8118        10863 :       tmp = gfc_finish_block (&se.pre);
    8119        10863 :       gfc_add_expr_to_block (&block, tmp);
    8120        10863 :       gfc_free_expr (expr);
    8121              :     }
    8122              : 
    8123         8623 :   if (code->expr1)
    8124              :     {
    8125         2604 :       tmp = build1_v (LABEL_EXPR, label_errmsg);
    8126         2604 :       gfc_add_expr_to_block (&block, tmp);
    8127              :     }
    8128              : 
    8129              :   /* Set ERRMSG - only needed if STAT is available.  */
    8130         8623 :   if (code->expr1 && code->expr2)
    8131              :     {
    8132           51 :       const char *msg = "Attempt to deallocate an unallocated object";
    8133           51 :       stmtblock_t errmsg_block;
    8134           51 :       tree errmsg_str, slen, dlen, cond;
    8135              : 
    8136           51 :       gfc_init_block (&errmsg_block);
    8137              : 
    8138           51 :       errmsg_str = gfc_create_var (pchar_type_node, "ERRMSG");
    8139           51 :       gfc_add_modify (&errmsg_block, errmsg_str,
    8140              :                 gfc_build_addr_expr (pchar_type_node,
    8141              :                         gfc_build_localized_cstring_const (msg)));
    8142           51 :       slen = build_int_cst (gfc_charlen_type_node, strlen (msg));
    8143           51 :       dlen = gfc_get_expr_charlen (code->expr2);
    8144              : 
    8145           51 :       gfc_trans_string_copy (&errmsg_block, dlen, errmsg, code->expr2->ts.kind,
    8146              :                              slen, errmsg_str, gfc_default_character_kind);
    8147           51 :       tmp = gfc_finish_block (&errmsg_block);
    8148              : 
    8149           51 :       cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, stat,
    8150           51 :                              build_int_cst (TREE_TYPE (stat), 0));
    8151           51 :       tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
    8152              :                              gfc_unlikely (cond, PRED_FORTRAN_FAIL_ALLOC), tmp,
    8153              :                              build_empty_stmt (input_location));
    8154              : 
    8155           51 :       gfc_add_expr_to_block (&block, tmp);
    8156              :     }
    8157              : 
    8158         8623 :   if (code->expr1 && TREE_USED (label_finish))
    8159              :     {
    8160           17 :       tmp = build1_v (LABEL_EXPR, label_finish);
    8161           17 :       gfc_add_expr_to_block (&block, tmp);
    8162              :     }
    8163              : 
    8164              :   /* Set STAT.  */
    8165         8623 :   if (code->expr1)
    8166              :     {
    8167         2604 :       gfc_init_se (&se, NULL);
    8168         2604 :       gfc_conv_expr_lhs (&se, code->expr1);
    8169         2604 :       tmp = convert (TREE_TYPE (se.expr), stat);
    8170         2604 :       gfc_add_modify (&block, se.expr, tmp);
    8171              :     }
    8172              : 
    8173         8623 :   return gfc_finish_block (&block);
    8174              : }
    8175              : 
    8176              : #include "gt-fortran-trans-stmt.h"
        

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.