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