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