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