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