1 /* Code translation -- generate GCC trees from gfc_code.
2 Copyright (C) 2002-2017 Free Software Foundation, Inc.
3 Contributed by Paul Brook
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
27 #include "gimple-expr.h" /* For create_tmp_var_raw. */
29 #include "stringpool.h"
30 #include "fold-const.h"
31 #include "tree-iterator.h"
32 #include "trans-stmt.h"
33 #include "trans-array.h"
34 #include "trans-types.h"
35 #include "trans-const.h"
37 /* Naming convention for backend interface code:
39 gfc_trans_* translate gfc_code into STMT trees.
41 gfc_conv_* expression conversion
43 gfc_get_* get a backend tree representation of a decl or type */
45 static gfc_file
*gfc_current_backend_file
;
47 const char gfc_msg_fault
[] = N_("Array reference out of bounds");
48 const char gfc_msg_wrong_return
[] = N_("Incorrect function return value");
51 /* Advance along TREE_CHAIN n times. */
54 gfc_advance_chain (tree t
, int n
)
58 gcc_assert (t
!= NULL_TREE
);
65 /* Strip off a legitimate source ending from the input
66 string NAME of length LEN. */
69 remove_suffix (char *name
, int len
)
73 for (i
= 2; i
< 8 && len
> i
; i
++)
75 if (name
[len
- i
] == '.')
84 /* Creates a variable declaration with a given TYPE. */
87 gfc_create_var_np (tree type
, const char *prefix
)
91 t
= create_tmp_var_raw (type
, prefix
);
93 /* No warnings for anonymous variables. */
95 TREE_NO_WARNING (t
) = 1;
101 /* Like above, but also adds it to the current scope. */
104 gfc_create_var (tree type
, const char *prefix
)
108 tmp
= gfc_create_var_np (type
, prefix
);
116 /* If the expression is not constant, evaluate it now. We assign the
117 result of the expression to an artificially created variable VAR, and
118 return a pointer to the VAR_DECL node for this variable. */
121 gfc_evaluate_now_loc (location_t loc
, tree expr
, stmtblock_t
* pblock
)
125 if (CONSTANT_CLASS_P (expr
))
128 var
= gfc_create_var (TREE_TYPE (expr
), NULL
);
129 gfc_add_modify_loc (loc
, pblock
, var
, expr
);
136 gfc_evaluate_now (tree expr
, stmtblock_t
* pblock
)
138 return gfc_evaluate_now_loc (input_location
, expr
, pblock
);
142 /* Build a MODIFY_EXPR node and add it to a given statement block PBLOCK.
143 A MODIFY_EXPR is an assignment:
147 gfc_add_modify_loc (location_t loc
, stmtblock_t
* pblock
, tree lhs
, tree rhs
)
152 t1
= TREE_TYPE (rhs
);
153 t2
= TREE_TYPE (lhs
);
154 /* Make sure that the types of the rhs and the lhs are the same
155 for scalar assignments. We should probably have something
156 similar for aggregates, but right now removing that check just
157 breaks everything. */
158 gcc_checking_assert (t1
== t2
159 || AGGREGATE_TYPE_P (TREE_TYPE (lhs
)));
161 tmp
= fold_build2_loc (loc
, MODIFY_EXPR
, void_type_node
, lhs
,
163 gfc_add_expr_to_block (pblock
, tmp
);
168 gfc_add_modify (stmtblock_t
* pblock
, tree lhs
, tree rhs
)
170 gfc_add_modify_loc (input_location
, pblock
, lhs
, rhs
);
174 /* Create a new scope/binding level and initialize a block. Care must be
175 taken when translating expressions as any temporaries will be placed in
176 the innermost scope. */
179 gfc_start_block (stmtblock_t
* block
)
181 /* Start a new binding level. */
183 block
->has_scope
= 1;
185 /* The block is empty. */
186 block
->head
= NULL_TREE
;
190 /* Initialize a block without creating a new scope. */
193 gfc_init_block (stmtblock_t
* block
)
195 block
->head
= NULL_TREE
;
196 block
->has_scope
= 0;
200 /* Sometimes we create a scope but it turns out that we don't actually
201 need it. This function merges the scope of BLOCK with its parent.
202 Only variable decls will be merged, you still need to add the code. */
205 gfc_merge_block_scope (stmtblock_t
* block
)
210 gcc_assert (block
->has_scope
);
211 block
->has_scope
= 0;
213 /* Remember the decls in this scope. */
217 /* Add them to the parent scope. */
218 while (decl
!= NULL_TREE
)
220 next
= DECL_CHAIN (decl
);
221 DECL_CHAIN (decl
) = NULL_TREE
;
229 /* Finish a scope containing a block of statements. */
232 gfc_finish_block (stmtblock_t
* stmtblock
)
238 expr
= stmtblock
->head
;
240 expr
= build_empty_stmt (input_location
);
242 stmtblock
->head
= NULL_TREE
;
244 if (stmtblock
->has_scope
)
250 block
= poplevel (1, 0);
251 expr
= build3_v (BIND_EXPR
, decl
, expr
, block
);
261 /* Build an ADDR_EXPR and cast the result to TYPE. If TYPE is NULL, the
262 natural type is used. */
265 gfc_build_addr_expr (tree type
, tree t
)
267 tree base_type
= TREE_TYPE (t
);
270 if (type
&& POINTER_TYPE_P (type
)
271 && TREE_CODE (base_type
) == ARRAY_TYPE
272 && TYPE_MAIN_VARIANT (TREE_TYPE (type
))
273 == TYPE_MAIN_VARIANT (TREE_TYPE (base_type
)))
275 tree min_val
= size_zero_node
;
276 tree type_domain
= TYPE_DOMAIN (base_type
);
277 if (type_domain
&& TYPE_MIN_VALUE (type_domain
))
278 min_val
= TYPE_MIN_VALUE (type_domain
);
279 t
= fold (build4_loc (input_location
, ARRAY_REF
, TREE_TYPE (type
),
280 t
, min_val
, NULL_TREE
, NULL_TREE
));
284 natural_type
= build_pointer_type (base_type
);
286 if (TREE_CODE (t
) == INDIRECT_REF
)
290 t
= TREE_OPERAND (t
, 0);
291 natural_type
= TREE_TYPE (t
);
295 tree base
= get_base_address (t
);
296 if (base
&& DECL_P (base
))
297 TREE_ADDRESSABLE (base
) = 1;
298 t
= fold_build1_loc (input_location
, ADDR_EXPR
, natural_type
, t
);
301 if (type
&& natural_type
!= type
)
302 t
= convert (type
, t
);
308 /* Build an ARRAY_REF with its natural type. */
311 gfc_build_array_ref (tree base
, tree offset
, tree decl
, tree vptr
)
313 tree type
= TREE_TYPE (base
);
317 if (GFC_ARRAY_TYPE_P (type
) && GFC_TYPE_ARRAY_RANK (type
) == 0)
319 gcc_assert (GFC_TYPE_ARRAY_CORANK (type
) > 0);
321 return fold_convert (TYPE_MAIN_VARIANT (type
), base
);
324 /* Scalar coarray, there is nothing to do. */
325 if (TREE_CODE (type
) != ARRAY_TYPE
)
327 gcc_assert (decl
== NULL_TREE
);
328 gcc_assert (integer_zerop (offset
));
332 type
= TREE_TYPE (type
);
334 /* Use pointer arithmetic for deferred character length array
336 if (type
&& TREE_CODE (type
) == ARRAY_TYPE
337 && TYPE_MAXVAL (TYPE_DOMAIN (type
)) != NULL_TREE
338 && (VAR_P (TYPE_MAXVAL (TYPE_DOMAIN (type
)))
339 || TREE_CODE (TYPE_MAXVAL (TYPE_DOMAIN (type
))) == INDIRECT_REF
)
341 && (TREE_CODE (TYPE_MAXVAL (TYPE_DOMAIN (type
))) == INDIRECT_REF
342 || TREE_CODE (decl
) == FUNCTION_DECL
343 || DECL_CONTEXT (TYPE_MAXVAL (TYPE_DOMAIN (type
)))
344 == DECL_CONTEXT (decl
)))
345 span
= TYPE_MAXVAL (TYPE_DOMAIN (type
));
350 TREE_ADDRESSABLE (base
) = 1;
352 /* Strip NON_LVALUE_EXPR nodes. */
353 STRIP_TYPE_NOPS (offset
);
355 /* If the array reference is to a pointer, whose target contains a
356 subreference, use the span that is stored with the backend decl
357 and reference the element with pointer arithmetic. */
358 if ((decl
&& (TREE_CODE (decl
) == FIELD_DECL
359 || VAR_OR_FUNCTION_DECL_P (decl
)
360 || TREE_CODE (decl
) == PARM_DECL
)
361 && ((GFC_DECL_SUBREF_ARRAY_P (decl
)
362 && !integer_zerop (GFC_DECL_SPAN (decl
)))
363 || GFC_DECL_CLASS (decl
)
364 || span
!= NULL_TREE
))
365 || vptr
!= NULL_TREE
)
369 if (GFC_DECL_CLASS (decl
))
371 /* When a temporary is in place for the class array, then the
372 original class' declaration is stored in the saved
374 if (DECL_LANG_SPECIFIC (decl
) && GFC_DECL_SAVED_DESCRIPTOR (decl
))
375 decl
= GFC_DECL_SAVED_DESCRIPTOR (decl
);
378 /* Allow for dummy arguments and other good things. */
379 if (POINTER_TYPE_P (TREE_TYPE (decl
)))
380 decl
= build_fold_indirect_ref_loc (input_location
, decl
);
382 /* Check if '_data' is an array descriptor. If it is not,
383 the array must be one of the components of the class
384 object, so return a normal array reference. */
385 if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (
386 gfc_class_data_get (decl
))))
387 return build4_loc (input_location
, ARRAY_REF
, type
, base
,
388 offset
, NULL_TREE
, NULL_TREE
);
391 span
= gfc_class_vtab_size_get (decl
);
393 else if (GFC_DECL_SUBREF_ARRAY_P (decl
))
394 span
= GFC_DECL_SPAN (decl
);
396 span
= fold_convert (gfc_array_index_type
, span
);
401 span
= gfc_vptr_size_get (vptr
);
405 offset
= fold_build2_loc (input_location
, MULT_EXPR
,
406 gfc_array_index_type
,
408 tmp
= gfc_build_addr_expr (pvoid_type_node
, base
);
409 tmp
= fold_build_pointer_plus_loc (input_location
, tmp
, offset
);
410 tmp
= fold_convert (build_pointer_type (type
), tmp
);
411 if (!TYPE_STRING_FLAG (type
))
412 tmp
= build_fold_indirect_ref_loc (input_location
, tmp
);
416 /* Otherwise use a straightforward array reference. */
417 return build4_loc (input_location
, ARRAY_REF
, type
, base
, offset
,
418 NULL_TREE
, NULL_TREE
);
422 /* Generate a call to print a runtime error possibly including multiple
423 arguments and a locus. */
426 trans_runtime_error_vararg (bool error
, locus
* where
, const char* msgid
,
439 /* Compute the number of extra arguments from the format string. */
440 for (p
= msgid
, nargs
= 0; *p
; p
++)
448 /* The code to generate the error. */
449 gfc_start_block (&block
);
453 line
= LOCATION_LINE (where
->lb
->location
);
454 message
= xasprintf ("At line %d of file %s", line
,
455 where
->lb
->file
->filename
);
458 message
= xasprintf ("In file '%s', around line %d",
459 gfc_source_file
, LOCATION_LINE (input_location
) + 1);
461 arg
= gfc_build_addr_expr (pchar_type_node
,
462 gfc_build_localized_cstring_const (message
));
465 message
= xasprintf ("%s", _(msgid
));
466 arg2
= gfc_build_addr_expr (pchar_type_node
,
467 gfc_build_localized_cstring_const (message
));
470 /* Build the argument array. */
471 argarray
= XALLOCAVEC (tree
, nargs
+ 2);
474 for (i
= 0; i
< nargs
; i
++)
475 argarray
[2 + i
] = va_arg (ap
, tree
);
477 /* Build the function call to runtime_(warning,error)_at; because of the
478 variable number of arguments, we can't use build_call_expr_loc dinput_location,
481 fntype
= TREE_TYPE (gfor_fndecl_runtime_error_at
);
483 fntype
= TREE_TYPE (gfor_fndecl_runtime_warning_at
);
485 loc
= where
? where
->lb
->location
: input_location
;
486 tmp
= fold_build_call_array_loc (loc
, TREE_TYPE (fntype
),
487 fold_build1_loc (loc
, ADDR_EXPR
,
488 build_pointer_type (fntype
),
490 ? gfor_fndecl_runtime_error_at
491 : gfor_fndecl_runtime_warning_at
),
492 nargs
+ 2, argarray
);
493 gfc_add_expr_to_block (&block
, tmp
);
495 return gfc_finish_block (&block
);
500 gfc_trans_runtime_error (bool error
, locus
* where
, const char* msgid
, ...)
505 va_start (ap
, msgid
);
506 result
= trans_runtime_error_vararg (error
, where
, msgid
, ap
);
512 /* Generate a runtime error if COND is true. */
515 gfc_trans_runtime_check (bool error
, bool once
, tree cond
, stmtblock_t
* pblock
,
516 locus
* where
, const char * msgid
, ...)
524 if (integer_zerop (cond
))
529 tmpvar
= gfc_create_var (boolean_type_node
, "print_warning");
530 TREE_STATIC (tmpvar
) = 1;
531 DECL_INITIAL (tmpvar
) = boolean_true_node
;
532 gfc_add_expr_to_block (pblock
, tmpvar
);
535 gfc_start_block (&block
);
537 /* For error, runtime_error_at already implies PRED_NORETURN. */
539 gfc_add_expr_to_block (&block
, build_predict_expr (PRED_FORTRAN_WARN_ONCE
,
542 /* The code to generate the error. */
543 va_start (ap
, msgid
);
544 gfc_add_expr_to_block (&block
,
545 trans_runtime_error_vararg (error
, where
,
550 gfc_add_modify (&block
, tmpvar
, boolean_false_node
);
552 body
= gfc_finish_block (&block
);
554 if (integer_onep (cond
))
556 gfc_add_expr_to_block (pblock
, body
);
561 cond
= fold_build2_loc (where
->lb
->location
, TRUTH_AND_EXPR
,
562 long_integer_type_node
, tmpvar
, cond
);
564 cond
= fold_convert (long_integer_type_node
, cond
);
566 tmp
= fold_build3_loc (where
->lb
->location
, COND_EXPR
, void_type_node
,
568 build_empty_stmt (where
->lb
->location
));
569 gfc_add_expr_to_block (pblock
, tmp
);
574 /* Call malloc to allocate size bytes of memory, with special conditions:
575 + if size == 0, return a malloced area of size 1,
576 + if malloc returns NULL, issue a runtime error. */
578 gfc_call_malloc (stmtblock_t
* block
, tree type
, tree size
)
580 tree tmp
, msg
, malloc_result
, null_result
, res
, malloc_tree
;
583 /* Create a variable to hold the result. */
584 res
= gfc_create_var (prvoid_type_node
, NULL
);
587 gfc_start_block (&block2
);
589 size
= fold_convert (size_type_node
, size
);
590 size
= fold_build2_loc (input_location
, MAX_EXPR
, size_type_node
, size
,
591 build_int_cst (size_type_node
, 1));
593 malloc_tree
= builtin_decl_explicit (BUILT_IN_MALLOC
);
594 gfc_add_modify (&block2
, res
,
595 fold_convert (prvoid_type_node
,
596 build_call_expr_loc (input_location
,
597 malloc_tree
, 1, size
)));
599 /* Optionally check whether malloc was successful. */
600 if (gfc_option
.rtcheck
& GFC_RTCHECK_MEM
)
602 null_result
= fold_build2_loc (input_location
, EQ_EXPR
,
603 boolean_type_node
, res
,
604 build_int_cst (pvoid_type_node
, 0));
605 msg
= gfc_build_addr_expr (pchar_type_node
,
606 gfc_build_localized_cstring_const ("Memory allocation failed"));
607 tmp
= fold_build3_loc (input_location
, COND_EXPR
, void_type_node
,
609 build_call_expr_loc (input_location
,
610 gfor_fndecl_os_error
, 1, msg
),
611 build_empty_stmt (input_location
));
612 gfc_add_expr_to_block (&block2
, tmp
);
615 malloc_result
= gfc_finish_block (&block2
);
616 gfc_add_expr_to_block (block
, malloc_result
);
619 res
= fold_convert (type
, res
);
624 /* Allocate memory, using an optional status argument.
626 This function follows the following pseudo-code:
629 allocate (size_t size, integer_type stat)
636 newmem = malloc (MAX (size, 1));
640 *stat = LIBERROR_ALLOCATION;
642 runtime_error ("Allocation would exceed memory limit");
647 gfc_allocate_using_malloc (stmtblock_t
* block
, tree pointer
,
648 tree size
, tree status
)
650 tree tmp
, error_cond
;
651 stmtblock_t on_error
;
652 tree status_type
= status
? TREE_TYPE (status
) : NULL_TREE
;
654 /* If successful and stat= is given, set status to 0. */
655 if (status
!= NULL_TREE
)
656 gfc_add_expr_to_block (block
,
657 fold_build2_loc (input_location
, MODIFY_EXPR
, status_type
,
658 status
, build_int_cst (status_type
, 0)));
660 /* The allocation itself. */
661 size
= fold_convert (size_type_node
, size
);
662 gfc_add_modify (block
, pointer
,
663 fold_convert (TREE_TYPE (pointer
),
664 build_call_expr_loc (input_location
,
665 builtin_decl_explicit (BUILT_IN_MALLOC
), 1,
666 fold_build2_loc (input_location
,
667 MAX_EXPR
, size_type_node
, size
,
668 build_int_cst (size_type_node
, 1)))));
670 /* What to do in case of error. */
671 gfc_start_block (&on_error
);
672 if (status
!= NULL_TREE
)
674 tmp
= fold_build2_loc (input_location
, MODIFY_EXPR
, status_type
, status
,
675 build_int_cst (status_type
, LIBERROR_ALLOCATION
));
676 gfc_add_expr_to_block (&on_error
, tmp
);
680 /* Here, os_error already implies PRED_NORETURN. */
681 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_os_error
, 1,
682 gfc_build_addr_expr (pchar_type_node
,
683 gfc_build_localized_cstring_const
684 ("Allocation would exceed memory limit")));
685 gfc_add_expr_to_block (&on_error
, tmp
);
688 error_cond
= fold_build2_loc (input_location
, EQ_EXPR
,
689 boolean_type_node
, pointer
,
690 build_int_cst (prvoid_type_node
, 0));
691 tmp
= fold_build3_loc (input_location
, COND_EXPR
, void_type_node
,
692 gfc_unlikely (error_cond
, PRED_FORTRAN_FAIL_ALLOC
),
693 gfc_finish_block (&on_error
),
694 build_empty_stmt (input_location
));
696 gfc_add_expr_to_block (block
, tmp
);
700 /* Allocate memory, using an optional status argument.
702 This function follows the following pseudo-code:
705 allocate (size_t size, void** token, int *stat, char* errmsg, int errlen)
709 newmem = _caf_register (size, regtype, token, &stat, errmsg, errlen);
713 gfc_allocate_using_caf_lib (stmtblock_t
* block
, tree pointer
, tree size
,
714 tree token
, tree status
, tree errmsg
, tree errlen
,
715 gfc_coarray_regtype alloc_type
)
719 gcc_assert (token
!= NULL_TREE
);
721 /* The allocation itself. */
722 if (status
== NULL_TREE
)
723 pstat
= null_pointer_node
;
725 pstat
= gfc_build_addr_expr (NULL_TREE
, status
);
727 if (errmsg
== NULL_TREE
)
729 gcc_assert(errlen
== NULL_TREE
);
730 errmsg
= null_pointer_node
;
731 errlen
= build_int_cst (integer_type_node
, 0);
734 size
= fold_convert (size_type_node
, size
);
735 tmp
= build_call_expr_loc (input_location
,
736 gfor_fndecl_caf_register
, 7,
737 fold_build2_loc (input_location
,
738 MAX_EXPR
, size_type_node
, size
, size_one_node
),
739 build_int_cst (integer_type_node
, alloc_type
),
740 token
, gfc_build_addr_expr (pvoid_type_node
, pointer
),
741 pstat
, errmsg
, errlen
);
743 gfc_add_expr_to_block (block
, tmp
);
745 /* It guarantees memory consistency within the same segment */
746 tmp
= gfc_build_string_const (strlen ("memory")+1, "memory"),
747 tmp
= build5_loc (input_location
, ASM_EXPR
, void_type_node
,
748 gfc_build_string_const (1, ""), NULL_TREE
, NULL_TREE
,
749 tree_cons (NULL_TREE
, tmp
, NULL_TREE
), NULL_TREE
);
750 ASM_VOLATILE_P (tmp
) = 1;
751 gfc_add_expr_to_block (block
, tmp
);
755 /* Generate code for an ALLOCATE statement when the argument is an
756 allocatable variable. If the variable is currently allocated, it is an
757 error to allocate it again.
759 This function follows the following pseudo-code:
762 allocate_allocatable (void *mem, size_t size, integer_type stat)
765 return allocate (size, stat);
769 stat = LIBERROR_ALLOCATION;
771 runtime_error ("Attempting to allocate already allocated variable");
775 expr must be set to the original expression being allocated for its locus
776 and variable name in case a runtime error has to be printed. */
778 gfc_allocate_allocatable (stmtblock_t
* block
, tree mem
, tree size
,
779 tree token
, tree status
, tree errmsg
, tree errlen
,
780 tree label_finish
, gfc_expr
* expr
, int corank
)
782 stmtblock_t alloc_block
;
783 tree tmp
, null_mem
, alloc
, error
;
784 tree type
= TREE_TYPE (mem
);
785 symbol_attribute caf_attr
;
786 bool need_assign
= false, refs_comp
= false;
787 gfc_coarray_regtype caf_alloc_type
= GFC_CAF_COARRAY_ALLOC
;
789 size
= fold_convert (size_type_node
, size
);
790 null_mem
= gfc_unlikely (fold_build2_loc (input_location
, NE_EXPR
,
791 boolean_type_node
, mem
,
792 build_int_cst (type
, 0)),
793 PRED_FORTRAN_REALLOC
);
795 /* If mem is NULL, we call gfc_allocate_using_malloc or
796 gfc_allocate_using_lib. */
797 gfc_start_block (&alloc_block
);
799 if (flag_coarray
== GFC_FCOARRAY_LIB
)
800 caf_attr
= gfc_caf_attr (expr
, true, &refs_comp
);
802 if (flag_coarray
== GFC_FCOARRAY_LIB
803 && (corank
> 0 || caf_attr
.codimension
))
805 tree cond
, sub_caf_tree
;
807 bool compute_special_caf_types_size
= false;
809 if (expr
->ts
.type
== BT_DERIVED
810 && expr
->ts
.u
.derived
->from_intmod
== INTMOD_ISO_FORTRAN_ENV
811 && expr
->ts
.u
.derived
->intmod_sym_id
== ISOFORTRAN_LOCK_TYPE
)
813 compute_special_caf_types_size
= true;
814 caf_alloc_type
= GFC_CAF_LOCK_ALLOC
;
816 else if (expr
->ts
.type
== BT_DERIVED
817 && expr
->ts
.u
.derived
->from_intmod
== INTMOD_ISO_FORTRAN_ENV
818 && expr
->ts
.u
.derived
->intmod_sym_id
== ISOFORTRAN_EVENT_TYPE
)
820 compute_special_caf_types_size
= true;
821 caf_alloc_type
= GFC_CAF_EVENT_ALLOC
;
823 else if (!caf_attr
.coarray_comp
&& refs_comp
)
824 /* Only allocatable components in a derived type coarray can be
826 caf_alloc_type
= GFC_CAF_COARRAY_ALLOC_ALLOCATE_ONLY
;
828 gfc_init_se (&se
, NULL
);
829 sub_caf_tree
= gfc_get_ultimate_alloc_ptr_comps_caf_token (&se
, expr
);
830 if (sub_caf_tree
== NULL_TREE
)
831 sub_caf_tree
= token
;
833 /* When mem is an array ref, then strip the .data-ref. */
834 if (TREE_CODE (mem
) == COMPONENT_REF
835 && !(GFC_ARRAY_TYPE_P (TREE_TYPE (mem
))))
836 tmp
= TREE_OPERAND (mem
, 0);
840 if (!(GFC_ARRAY_TYPE_P (TREE_TYPE (tmp
))
841 && TYPE_LANG_SPECIFIC (TREE_TYPE (tmp
))->corank
== 0)
842 && !GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp
)))
844 symbol_attribute attr
;
846 gfc_clear_attr (&attr
);
847 tmp
= gfc_conv_scalar_to_descriptor (&se
, mem
, attr
);
850 gfc_add_block_to_block (&alloc_block
, &se
.pre
);
852 /* In the front end, we represent the lock variable as pointer. However,
853 the FE only passes the pointer around and leaves the actual
854 representation to the library. Hence, we have to convert back to the
855 number of elements. */
856 if (compute_special_caf_types_size
)
857 size
= fold_build2_loc (input_location
, TRUNC_DIV_EXPR
, size_type_node
,
858 size
, TYPE_SIZE_UNIT (ptr_type_node
));
860 gfc_allocate_using_caf_lib (&alloc_block
, tmp
, size
, sub_caf_tree
,
861 status
, errmsg
, errlen
, caf_alloc_type
);
863 gfc_add_modify (&alloc_block
, mem
, fold_convert (TREE_TYPE (mem
),
864 gfc_conv_descriptor_data_get (tmp
)));
865 if (status
!= NULL_TREE
)
867 TREE_USED (label_finish
) = 1;
868 tmp
= build1_v (GOTO_EXPR
, label_finish
);
869 cond
= fold_build2_loc (input_location
, NE_EXPR
, boolean_type_node
,
870 status
, build_zero_cst (TREE_TYPE (status
)));
871 tmp
= fold_build3_loc (input_location
, COND_EXPR
, void_type_node
,
872 gfc_unlikely (cond
, PRED_FORTRAN_FAIL_ALLOC
),
873 tmp
, build_empty_stmt (input_location
));
874 gfc_add_expr_to_block (&alloc_block
, tmp
);
878 gfc_allocate_using_malloc (&alloc_block
, mem
, size
, status
);
880 alloc
= gfc_finish_block (&alloc_block
);
882 /* If mem is not NULL, we issue a runtime error or set the
888 gcc_assert (expr
->expr_type
== EXPR_VARIABLE
&& expr
->symtree
);
889 varname
= gfc_build_cstring_const (expr
->symtree
->name
);
890 varname
= gfc_build_addr_expr (pchar_type_node
, varname
);
892 error
= gfc_trans_runtime_error (true, &expr
->where
,
893 "Attempting to allocate already"
894 " allocated variable '%s'",
898 error
= gfc_trans_runtime_error (true, NULL
,
899 "Attempting to allocate already allocated"
902 if (status
!= NULL_TREE
)
904 tree status_type
= TREE_TYPE (status
);
906 error
= fold_build2_loc (input_location
, MODIFY_EXPR
, status_type
,
907 status
, build_int_cst (status_type
, LIBERROR_ALLOCATION
));
910 tmp
= fold_build3_loc (input_location
, COND_EXPR
, void_type_node
, null_mem
,
912 gfc_add_expr_to_block (block
, tmp
);
916 /* Free a given variable. */
919 gfc_call_free (tree var
)
921 return build_call_expr_loc (input_location
,
922 builtin_decl_explicit (BUILT_IN_FREE
),
923 1, fold_convert (pvoid_type_node
, var
));
927 /* Build a call to a FINAL procedure, which finalizes "var". */
930 gfc_build_final_call (gfc_typespec ts
, gfc_expr
*final_wrapper
, gfc_expr
*var
,
931 bool fini_coarray
, gfc_expr
*class_size
)
935 tree final_fndecl
, array
, size
, tmp
;
936 symbol_attribute attr
;
938 gcc_assert (final_wrapper
->expr_type
== EXPR_VARIABLE
);
941 gfc_start_block (&block
);
942 gfc_init_se (&se
, NULL
);
943 gfc_conv_expr (&se
, final_wrapper
);
944 final_fndecl
= se
.expr
;
945 if (POINTER_TYPE_P (TREE_TYPE (final_fndecl
)))
946 final_fndecl
= build_fold_indirect_ref_loc (input_location
, final_fndecl
);
948 if (ts
.type
== BT_DERIVED
)
952 gcc_assert (!class_size
);
953 elem_size
= gfc_typenode_for_spec (&ts
);
954 elem_size
= TYPE_SIZE_UNIT (elem_size
);
955 size
= fold_convert (gfc_array_index_type
, elem_size
);
957 gfc_init_se (&se
, NULL
);
961 se
.descriptor_only
= 1;
962 gfc_conv_expr_descriptor (&se
, var
);
967 gfc_conv_expr (&se
, var
);
968 gcc_assert (se
.pre
.head
== NULL_TREE
&& se
.post
.head
== NULL_TREE
);
971 /* No copy back needed, hence set attr's allocatable/pointer
973 gfc_clear_attr (&attr
);
974 gfc_init_se (&se
, NULL
);
975 array
= gfc_conv_scalar_to_descriptor (&se
, array
, attr
);
976 gcc_assert (se
.post
.head
== NULL_TREE
);
981 gfc_expr
*array_expr
;
982 gcc_assert (class_size
);
983 gfc_init_se (&se
, NULL
);
984 gfc_conv_expr (&se
, class_size
);
985 gfc_add_block_to_block (&block
, &se
.pre
);
986 gcc_assert (se
.post
.head
== NULL_TREE
);
989 array_expr
= gfc_copy_expr (var
);
990 gfc_init_se (&se
, NULL
);
992 if (array_expr
->rank
)
994 gfc_add_class_array_ref (array_expr
);
995 se
.descriptor_only
= 1;
996 gfc_conv_expr_descriptor (&se
, array_expr
);
1001 gfc_add_data_component (array_expr
);
1002 gfc_conv_expr (&se
, array_expr
);
1003 gfc_add_block_to_block (&block
, &se
.pre
);
1004 gcc_assert (se
.post
.head
== NULL_TREE
);
1006 if (TREE_CODE (array
) == ADDR_EXPR
1007 && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (array
, 0))))
1008 tmp
= TREE_OPERAND (array
, 0);
1010 if (!gfc_is_coarray (array_expr
))
1012 /* No copy back needed, hence set attr's allocatable/pointer
1014 gfc_clear_attr (&attr
);
1015 gfc_init_se (&se
, NULL
);
1016 array
= gfc_conv_scalar_to_descriptor (&se
, array
, attr
);
1018 gcc_assert (se
.post
.head
== NULL_TREE
);
1020 gfc_free_expr (array_expr
);
1023 if (!POINTER_TYPE_P (TREE_TYPE (array
)))
1024 array
= gfc_build_addr_expr (NULL
, array
);
1026 gfc_add_block_to_block (&block
, &se
.pre
);
1027 tmp
= build_call_expr_loc (input_location
,
1028 final_fndecl
, 3, array
,
1029 size
, fini_coarray
? boolean_true_node
1030 : boolean_false_node
);
1031 gfc_add_block_to_block (&block
, &se
.post
);
1032 gfc_add_expr_to_block (&block
, tmp
);
1033 return gfc_finish_block (&block
);
1038 gfc_add_comp_finalizer_call (stmtblock_t
*block
, tree decl
, gfc_component
*comp
,
1043 tree final_fndecl
, size
, array
, tmp
, cond
;
1044 symbol_attribute attr
;
1045 gfc_expr
*final_expr
= NULL
;
1047 if (comp
->ts
.type
!= BT_DERIVED
&& comp
->ts
.type
!= BT_CLASS
)
1050 gfc_init_block (&block2
);
1052 if (comp
->ts
.type
== BT_DERIVED
)
1054 if (comp
->attr
.pointer
)
1057 gfc_is_finalizable (comp
->ts
.u
.derived
, &final_expr
);
1061 gfc_init_se (&se
, NULL
);
1062 gfc_conv_expr (&se
, final_expr
);
1063 final_fndecl
= se
.expr
;
1064 size
= gfc_typenode_for_spec (&comp
->ts
);
1065 size
= TYPE_SIZE_UNIT (size
);
1066 size
= fold_convert (gfc_array_index_type
, size
);
1070 else /* comp->ts.type == BT_CLASS. */
1072 if (CLASS_DATA (comp
)->attr
.class_pointer
)
1075 gfc_is_finalizable (CLASS_DATA (comp
)->ts
.u
.derived
, &final_expr
);
1076 final_fndecl
= gfc_class_vtab_final_get (decl
);
1077 size
= gfc_class_vtab_size_get (decl
);
1078 array
= gfc_class_data_get (decl
);
1081 if (comp
->attr
.allocatable
1082 || (comp
->ts
.type
== BT_CLASS
&& CLASS_DATA (comp
)->attr
.allocatable
))
1084 tmp
= GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (array
))
1085 ? gfc_conv_descriptor_data_get (array
) : array
;
1086 cond
= fold_build2_loc (input_location
, NE_EXPR
, boolean_type_node
,
1087 tmp
, fold_convert (TREE_TYPE (tmp
),
1088 null_pointer_node
));
1091 cond
= boolean_true_node
;
1093 if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (array
)))
1095 gfc_clear_attr (&attr
);
1096 gfc_init_se (&se
, NULL
);
1097 array
= gfc_conv_scalar_to_descriptor (&se
, array
, attr
);
1098 gfc_add_block_to_block (&block2
, &se
.pre
);
1099 gcc_assert (se
.post
.head
== NULL_TREE
);
1102 if (!POINTER_TYPE_P (TREE_TYPE (array
)))
1103 array
= gfc_build_addr_expr (NULL
, array
);
1107 tmp
= fold_build2_loc (input_location
, NE_EXPR
, boolean_type_node
,
1109 fold_convert (TREE_TYPE (final_fndecl
),
1110 null_pointer_node
));
1111 cond
= fold_build2_loc (input_location
, TRUTH_ANDIF_EXPR
,
1112 boolean_type_node
, cond
, tmp
);
1115 if (POINTER_TYPE_P (TREE_TYPE (final_fndecl
)))
1116 final_fndecl
= build_fold_indirect_ref_loc (input_location
, final_fndecl
);
1118 tmp
= build_call_expr_loc (input_location
,
1119 final_fndecl
, 3, array
,
1120 size
, fini_coarray
? boolean_true_node
1121 : boolean_false_node
);
1122 gfc_add_expr_to_block (&block2
, tmp
);
1123 tmp
= gfc_finish_block (&block2
);
1125 tmp
= fold_build3_loc (input_location
, COND_EXPR
, void_type_node
, cond
, tmp
,
1126 build_empty_stmt (input_location
));
1127 gfc_add_expr_to_block (block
, tmp
);
1133 /* Add a call to the finalizer, using the passed *expr. Returns
1134 true when a finalizer call has been inserted. */
1137 gfc_add_finalizer_call (stmtblock_t
*block
, gfc_expr
*expr2
)
1142 gfc_expr
*final_expr
= NULL
;
1143 gfc_expr
*elem_size
= NULL
;
1144 bool has_finalizer
= false;
1146 if (!expr2
|| (expr2
->ts
.type
!= BT_DERIVED
&& expr2
->ts
.type
!= BT_CLASS
))
1149 if (expr2
->ts
.type
== BT_DERIVED
)
1151 gfc_is_finalizable (expr2
->ts
.u
.derived
, &final_expr
);
1156 /* If we have a class array, we need go back to the class
1158 expr
= gfc_copy_expr (expr2
);
1160 if (expr
->ref
&& expr
->ref
->next
&& !expr
->ref
->next
->next
1161 && expr
->ref
->next
->type
== REF_ARRAY
1162 && expr
->ref
->type
== REF_COMPONENT
1163 && strcmp (expr
->ref
->u
.c
.component
->name
, "_data") == 0)
1165 gfc_free_ref_list (expr
->ref
);
1169 for (ref
= expr
->ref
; ref
; ref
= ref
->next
)
1170 if (ref
->next
&& ref
->next
->next
&& !ref
->next
->next
->next
1171 && ref
->next
->next
->type
== REF_ARRAY
1172 && ref
->next
->type
== REF_COMPONENT
1173 && strcmp (ref
->next
->u
.c
.component
->name
, "_data") == 0)
1175 gfc_free_ref_list (ref
->next
);
1179 if (expr
->ts
.type
== BT_CLASS
)
1181 has_finalizer
= gfc_is_finalizable (expr
->ts
.u
.derived
, NULL
);
1183 if (!expr2
->rank
&& !expr2
->ref
&& CLASS_DATA (expr2
->symtree
->n
.sym
)->as
)
1184 expr
->rank
= CLASS_DATA (expr2
->symtree
->n
.sym
)->as
->rank
;
1186 final_expr
= gfc_copy_expr (expr
);
1187 gfc_add_vptr_component (final_expr
);
1188 gfc_add_final_component (final_expr
);
1190 elem_size
= gfc_copy_expr (expr
);
1191 gfc_add_vptr_component (elem_size
);
1192 gfc_add_size_component (elem_size
);
1195 gcc_assert (final_expr
->expr_type
== EXPR_VARIABLE
);
1197 tmp
= gfc_build_final_call (expr
->ts
, final_expr
, expr
,
1200 if (expr
->ts
.type
== BT_CLASS
&& !has_finalizer
)
1205 gfc_init_se (&se
, NULL
);
1206 se
.want_pointer
= 1;
1207 gfc_conv_expr (&se
, final_expr
);
1208 cond
= fold_build2_loc (input_location
, NE_EXPR
, boolean_type_node
,
1209 se
.expr
, build_int_cst (TREE_TYPE (se
.expr
), 0));
1211 /* For CLASS(*) not only sym->_vtab->_final can be NULL
1212 but already sym->_vtab itself. */
1213 if (UNLIMITED_POLY (expr
))
1216 gfc_expr
*vptr_expr
;
1218 vptr_expr
= gfc_copy_expr (expr
);
1219 gfc_add_vptr_component (vptr_expr
);
1221 gfc_init_se (&se
, NULL
);
1222 se
.want_pointer
= 1;
1223 gfc_conv_expr (&se
, vptr_expr
);
1224 gfc_free_expr (vptr_expr
);
1226 cond2
= fold_build2_loc (input_location
, NE_EXPR
, boolean_type_node
,
1228 build_int_cst (TREE_TYPE (se
.expr
), 0));
1229 cond
= fold_build2_loc (input_location
, TRUTH_ANDIF_EXPR
,
1230 boolean_type_node
, cond2
, cond
);
1233 tmp
= fold_build3_loc (input_location
, COND_EXPR
, void_type_node
,
1234 cond
, tmp
, build_empty_stmt (input_location
));
1237 gfc_add_expr_to_block (block
, tmp
);
1243 /* User-deallocate; we emit the code directly from the front-end, and the
1244 logic is the same as the previous library function:
1247 deallocate (void *pointer, GFC_INTEGER_4 * stat)
1254 runtime_error ("Attempt to DEALLOCATE unallocated memory.");
1264 In this front-end version, status doesn't have to be GFC_INTEGER_4.
1265 Moreover, if CAN_FAIL is true, then we will not emit a runtime error,
1266 even when no status variable is passed to us (this is used for
1267 unconditional deallocation generated by the front-end at end of
1270 If a runtime-message is possible, `expr' must point to the original
1271 expression being deallocated for its locus and variable name.
1273 For coarrays, "pointer" must be the array descriptor and not its
1276 COARRAY_DEALLOC_MODE gives the mode unregister coarrays. Available modes are
1277 the ones of GFC_CAF_DEREGTYPE, -1 when the mode for deregistration is to be
1278 analyzed and set by this routine, and -2 to indicate that a non-coarray is to
1281 gfc_deallocate_with_status (tree pointer
, tree status
, tree errmsg
,
1282 tree errlen
, tree label_finish
,
1283 bool can_fail
, gfc_expr
* expr
,
1284 int coarray_dealloc_mode
, tree add_when_allocated
,
1287 stmtblock_t null
, non_null
;
1288 tree cond
, tmp
, error
;
1289 tree status_type
= NULL_TREE
;
1290 tree token
= NULL_TREE
;
1291 gfc_coarray_deregtype caf_dereg_type
= GFC_CAF_COARRAY_DEREGISTER
;
1293 if (coarray_dealloc_mode
>= GFC_CAF_COARRAY_ANALYZE
)
1295 if (flag_coarray
== GFC_FCOARRAY_LIB
)
1301 tree caf_type
, caf_decl
= pointer
;
1302 pointer
= gfc_conv_descriptor_data_get (caf_decl
);
1303 caf_type
= TREE_TYPE (caf_decl
);
1304 STRIP_NOPS (pointer
);
1305 if (GFC_DESCRIPTOR_TYPE_P (caf_type
))
1306 token
= gfc_conv_descriptor_token (caf_decl
);
1307 else if (DECL_LANG_SPECIFIC (caf_decl
)
1308 && GFC_DECL_TOKEN (caf_decl
) != NULL_TREE
)
1309 token
= GFC_DECL_TOKEN (caf_decl
);
1312 gcc_assert (GFC_ARRAY_TYPE_P (caf_type
)
1313 && GFC_TYPE_ARRAY_CAF_TOKEN (caf_type
)
1315 token
= GFC_TYPE_ARRAY_CAF_TOKEN (caf_type
);
1319 if (coarray_dealloc_mode
== GFC_CAF_COARRAY_ANALYZE
)
1322 if (expr
&& !gfc_caf_attr (expr
, false, &comp_ref
).coarray_comp
1324 caf_dereg_type
= GFC_CAF_COARRAY_DEALLOCATE_ONLY
;
1325 // else do a deregister as set by default.
1328 caf_dereg_type
= (enum gfc_coarray_deregtype
) coarray_dealloc_mode
;
1330 else if (flag_coarray
== GFC_FCOARRAY_SINGLE
)
1331 pointer
= gfc_conv_descriptor_data_get (pointer
);
1333 else if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (pointer
)))
1334 pointer
= gfc_conv_descriptor_data_get (pointer
);
1336 cond
= fold_build2_loc (input_location
, EQ_EXPR
, boolean_type_node
, pointer
,
1337 build_int_cst (TREE_TYPE (pointer
), 0));
1339 /* When POINTER is NULL, we set STATUS to 1 if it's present, otherwise
1340 we emit a runtime error. */
1341 gfc_start_block (&null
);
1346 gcc_assert (expr
&& expr
->expr_type
== EXPR_VARIABLE
&& expr
->symtree
);
1348 varname
= gfc_build_cstring_const (expr
->symtree
->name
);
1349 varname
= gfc_build_addr_expr (pchar_type_node
, varname
);
1351 error
= gfc_trans_runtime_error (true, &expr
->where
,
1352 "Attempt to DEALLOCATE unallocated '%s'",
1356 error
= build_empty_stmt (input_location
);
1358 if (status
!= NULL_TREE
&& !integer_zerop (status
))
1362 status_type
= TREE_TYPE (TREE_TYPE (status
));
1363 cond2
= fold_build2_loc (input_location
, NE_EXPR
, boolean_type_node
,
1364 status
, build_int_cst (TREE_TYPE (status
), 0));
1365 tmp
= fold_build2_loc (input_location
, MODIFY_EXPR
, status_type
,
1366 fold_build1_loc (input_location
, INDIRECT_REF
,
1367 status_type
, status
),
1368 build_int_cst (status_type
, 1));
1369 error
= fold_build3_loc (input_location
, COND_EXPR
, void_type_node
,
1373 gfc_add_expr_to_block (&null
, error
);
1375 /* When POINTER is not NULL, we free it. */
1376 gfc_start_block (&non_null
);
1377 if (add_when_allocated
)
1378 gfc_add_expr_to_block (&non_null
, add_when_allocated
);
1379 gfc_add_finalizer_call (&non_null
, expr
);
1380 if (coarray_dealloc_mode
== GFC_CAF_COARRAY_NOCOARRAY
1381 || flag_coarray
!= GFC_FCOARRAY_LIB
)
1383 tmp
= build_call_expr_loc (input_location
,
1384 builtin_decl_explicit (BUILT_IN_FREE
), 1,
1385 fold_convert (pvoid_type_node
, pointer
));
1386 gfc_add_expr_to_block (&non_null
, tmp
);
1387 gfc_add_modify (&non_null
, pointer
, build_int_cst (TREE_TYPE (pointer
),
1390 if (status
!= NULL_TREE
&& !integer_zerop (status
))
1392 /* We set STATUS to zero if it is present. */
1393 tree status_type
= TREE_TYPE (TREE_TYPE (status
));
1396 cond2
= fold_build2_loc (input_location
, NE_EXPR
, boolean_type_node
,
1398 build_int_cst (TREE_TYPE (status
), 0));
1399 tmp
= fold_build2_loc (input_location
, MODIFY_EXPR
, status_type
,
1400 fold_build1_loc (input_location
, INDIRECT_REF
,
1401 status_type
, status
),
1402 build_int_cst (status_type
, 0));
1403 tmp
= fold_build3_loc (input_location
, COND_EXPR
, void_type_node
,
1404 gfc_unlikely (cond2
, PRED_FORTRAN_FAIL_ALLOC
),
1405 tmp
, build_empty_stmt (input_location
));
1406 gfc_add_expr_to_block (&non_null
, tmp
);
1411 tree cond2
, pstat
= null_pointer_node
;
1413 if (errmsg
== NULL_TREE
)
1415 gcc_assert (errlen
== NULL_TREE
);
1416 errmsg
= null_pointer_node
;
1417 errlen
= build_zero_cst (integer_type_node
);
1421 gcc_assert (errlen
!= NULL_TREE
);
1422 if (!POINTER_TYPE_P (TREE_TYPE (errmsg
)))
1423 errmsg
= gfc_build_addr_expr (NULL_TREE
, errmsg
);
1426 if (status
!= NULL_TREE
&& !integer_zerop (status
))
1428 gcc_assert (status_type
== integer_type_node
);
1432 token
= gfc_build_addr_expr (NULL_TREE
, token
);
1433 gcc_assert (caf_dereg_type
> GFC_CAF_COARRAY_ANALYZE
);
1434 tmp
= build_call_expr_loc (input_location
,
1435 gfor_fndecl_caf_deregister
, 5,
1436 token
, build_int_cst (integer_type_node
,
1438 pstat
, errmsg
, errlen
);
1439 gfc_add_expr_to_block (&non_null
, tmp
);
1441 /* It guarantees memory consistency within the same segment */
1442 tmp
= gfc_build_string_const (strlen ("memory")+1, "memory"),
1443 tmp
= build5_loc (input_location
, ASM_EXPR
, void_type_node
,
1444 gfc_build_string_const (1, ""), NULL_TREE
, NULL_TREE
,
1445 tree_cons (NULL_TREE
, tmp
, NULL_TREE
), NULL_TREE
);
1446 ASM_VOLATILE_P (tmp
) = 1;
1447 gfc_add_expr_to_block (&non_null
, tmp
);
1449 if (status
!= NULL_TREE
)
1451 tree stat
= build_fold_indirect_ref_loc (input_location
, status
);
1452 tree nullify
= fold_build2_loc (input_location
, MODIFY_EXPR
,
1453 void_type_node
, pointer
,
1454 build_int_cst (TREE_TYPE (pointer
),
1457 TREE_USED (label_finish
) = 1;
1458 tmp
= build1_v (GOTO_EXPR
, label_finish
);
1459 cond2
= fold_build2_loc (input_location
, NE_EXPR
, boolean_type_node
,
1460 stat
, build_zero_cst (TREE_TYPE (stat
)));
1461 tmp
= fold_build3_loc (input_location
, COND_EXPR
, void_type_node
,
1462 gfc_unlikely (cond2
, PRED_FORTRAN_REALLOC
),
1464 gfc_add_expr_to_block (&non_null
, tmp
);
1467 gfc_add_modify (&non_null
, pointer
, build_int_cst (TREE_TYPE (pointer
),
1471 return fold_build3_loc (input_location
, COND_EXPR
, void_type_node
, cond
,
1472 gfc_finish_block (&null
),
1473 gfc_finish_block (&non_null
));
1477 /* Generate code for deallocation of allocatable scalars (variables or
1478 components). Before the object itself is freed, any allocatable
1479 subcomponents are being deallocated. */
1482 gfc_deallocate_scalar_with_status (tree pointer
, tree status
, tree label_finish
,
1483 bool can_fail
, gfc_expr
* expr
,
1484 gfc_typespec ts
, bool coarray
)
1486 stmtblock_t null
, non_null
;
1487 tree cond
, tmp
, error
;
1488 bool finalizable
, comp_ref
;
1489 gfc_coarray_deregtype caf_dereg_type
= GFC_CAF_COARRAY_DEREGISTER
;
1491 if (coarray
&& expr
&& !gfc_caf_attr (expr
, false, &comp_ref
).coarray_comp
1493 caf_dereg_type
= GFC_CAF_COARRAY_DEALLOCATE_ONLY
;
1495 cond
= fold_build2_loc (input_location
, EQ_EXPR
, boolean_type_node
, pointer
,
1496 build_int_cst (TREE_TYPE (pointer
), 0));
1498 /* When POINTER is NULL, we set STATUS to 1 if it's present, otherwise
1499 we emit a runtime error. */
1500 gfc_start_block (&null
);
1505 gcc_assert (expr
&& expr
->expr_type
== EXPR_VARIABLE
&& expr
->symtree
);
1507 varname
= gfc_build_cstring_const (expr
->symtree
->name
);
1508 varname
= gfc_build_addr_expr (pchar_type_node
, varname
);
1510 error
= gfc_trans_runtime_error (true, &expr
->where
,
1511 "Attempt to DEALLOCATE unallocated '%s'",
1515 error
= build_empty_stmt (input_location
);
1517 if (status
!= NULL_TREE
&& !integer_zerop (status
))
1519 tree status_type
= TREE_TYPE (TREE_TYPE (status
));
1522 cond2
= fold_build2_loc (input_location
, NE_EXPR
, boolean_type_node
,
1523 status
, build_int_cst (TREE_TYPE (status
), 0));
1524 tmp
= fold_build2_loc (input_location
, MODIFY_EXPR
, status_type
,
1525 fold_build1_loc (input_location
, INDIRECT_REF
,
1526 status_type
, status
),
1527 build_int_cst (status_type
, 1));
1528 error
= fold_build3_loc (input_location
, COND_EXPR
, void_type_node
,
1531 gfc_add_expr_to_block (&null
, error
);
1533 /* When POINTER is not NULL, we free it. */
1534 gfc_start_block (&non_null
);
1536 /* Free allocatable components. */
1537 finalizable
= gfc_add_finalizer_call (&non_null
, expr
);
1538 if (!finalizable
&& ts
.type
== BT_DERIVED
&& ts
.u
.derived
->attr
.alloc_comp
)
1540 int caf_mode
= coarray
1541 ? ((caf_dereg_type
== GFC_CAF_COARRAY_DEALLOCATE_ONLY
1542 ? GFC_STRUCTURE_CAF_MODE_DEALLOC_ONLY
: 0)
1543 | GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY
1544 | GFC_STRUCTURE_CAF_MODE_IN_COARRAY
)
1546 if (coarray
&& GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (pointer
)))
1547 tmp
= gfc_conv_descriptor_data_get (pointer
);
1549 tmp
= build_fold_indirect_ref_loc (input_location
, pointer
);
1550 tmp
= gfc_deallocate_alloc_comp (ts
.u
.derived
, tmp
, 0, caf_mode
);
1551 gfc_add_expr_to_block (&non_null
, tmp
);
1554 if (!coarray
|| flag_coarray
== GFC_FCOARRAY_SINGLE
)
1556 tmp
= build_call_expr_loc (input_location
,
1557 builtin_decl_explicit (BUILT_IN_FREE
), 1,
1558 fold_convert (pvoid_type_node
, pointer
));
1559 gfc_add_expr_to_block (&non_null
, tmp
);
1561 if (status
!= NULL_TREE
&& !integer_zerop (status
))
1563 /* We set STATUS to zero if it is present. */
1564 tree status_type
= TREE_TYPE (TREE_TYPE (status
));
1567 cond2
= fold_build2_loc (input_location
, NE_EXPR
, boolean_type_node
,
1569 build_int_cst (TREE_TYPE (status
), 0));
1570 tmp
= fold_build2_loc (input_location
, MODIFY_EXPR
, status_type
,
1571 fold_build1_loc (input_location
, INDIRECT_REF
,
1572 status_type
, status
),
1573 build_int_cst (status_type
, 0));
1574 tmp
= fold_build3_loc (input_location
, COND_EXPR
, void_type_node
,
1575 cond2
, tmp
, build_empty_stmt (input_location
));
1576 gfc_add_expr_to_block (&non_null
, tmp
);
1582 tree pstat
= null_pointer_node
;
1585 gfc_init_se (&se
, NULL
);
1586 token
= gfc_get_ultimate_alloc_ptr_comps_caf_token (&se
, expr
);
1587 gcc_assert (token
!= NULL_TREE
);
1589 if (status
!= NULL_TREE
&& !integer_zerop (status
))
1591 gcc_assert (TREE_TYPE (TREE_TYPE (status
)) == integer_type_node
);
1595 tmp
= build_call_expr_loc (input_location
,
1596 gfor_fndecl_caf_deregister
, 5,
1597 token
, build_int_cst (integer_type_node
,
1599 pstat
, null_pointer_node
, integer_zero_node
);
1600 gfc_add_expr_to_block (&non_null
, tmp
);
1602 /* It guarantees memory consistency within the same segment. */
1603 tmp
= gfc_build_string_const (strlen ("memory")+1, "memory");
1604 tmp
= build5_loc (input_location
, ASM_EXPR
, void_type_node
,
1605 gfc_build_string_const (1, ""), NULL_TREE
, NULL_TREE
,
1606 tree_cons (NULL_TREE
, tmp
, NULL_TREE
), NULL_TREE
);
1607 ASM_VOLATILE_P (tmp
) = 1;
1608 gfc_add_expr_to_block (&non_null
, tmp
);
1610 if (status
!= NULL_TREE
)
1612 tree stat
= build_fold_indirect_ref_loc (input_location
, status
);
1615 TREE_USED (label_finish
) = 1;
1616 tmp
= build1_v (GOTO_EXPR
, label_finish
);
1617 cond2
= fold_build2_loc (input_location
, NE_EXPR
, boolean_type_node
,
1618 stat
, build_zero_cst (TREE_TYPE (stat
)));
1619 tmp
= fold_build3_loc (input_location
, COND_EXPR
, void_type_node
,
1620 gfc_unlikely (cond2
, PRED_FORTRAN_REALLOC
),
1621 tmp
, build_empty_stmt (input_location
));
1622 gfc_add_expr_to_block (&non_null
, tmp
);
1626 return fold_build3_loc (input_location
, COND_EXPR
, void_type_node
, cond
,
1627 gfc_finish_block (&null
),
1628 gfc_finish_block (&non_null
));
1631 /* Reallocate MEM so it has SIZE bytes of data. This behaves like the
1632 following pseudo-code:
1635 internal_realloc (void *mem, size_t size)
1637 res = realloc (mem, size);
1638 if (!res && size != 0)
1639 _gfortran_os_error ("Allocation would exceed memory limit");
1644 gfc_call_realloc (stmtblock_t
* block
, tree mem
, tree size
)
1646 tree msg
, res
, nonzero
, null_result
, tmp
;
1647 tree type
= TREE_TYPE (mem
);
1649 /* Only evaluate the size once. */
1650 size
= save_expr (fold_convert (size_type_node
, size
));
1652 /* Create a variable to hold the result. */
1653 res
= gfc_create_var (type
, NULL
);
1655 /* Call realloc and check the result. */
1656 tmp
= build_call_expr_loc (input_location
,
1657 builtin_decl_explicit (BUILT_IN_REALLOC
), 2,
1658 fold_convert (pvoid_type_node
, mem
), size
);
1659 gfc_add_modify (block
, res
, fold_convert (type
, tmp
));
1660 null_result
= fold_build2_loc (input_location
, EQ_EXPR
, boolean_type_node
,
1661 res
, build_int_cst (pvoid_type_node
, 0));
1662 nonzero
= fold_build2_loc (input_location
, NE_EXPR
, boolean_type_node
, size
,
1663 build_int_cst (size_type_node
, 0));
1664 null_result
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
, boolean_type_node
,
1665 null_result
, nonzero
);
1666 msg
= gfc_build_addr_expr (pchar_type_node
, gfc_build_localized_cstring_const
1667 ("Allocation would exceed memory limit"));
1668 tmp
= fold_build3_loc (input_location
, COND_EXPR
, void_type_node
,
1670 build_call_expr_loc (input_location
,
1671 gfor_fndecl_os_error
, 1, msg
),
1672 build_empty_stmt (input_location
));
1673 gfc_add_expr_to_block (block
, tmp
);
1679 /* Add an expression to another one, either at the front or the back. */
1682 add_expr_to_chain (tree
* chain
, tree expr
, bool front
)
1684 if (expr
== NULL_TREE
|| IS_EMPTY_STMT (expr
))
1689 if (TREE_CODE (*chain
) != STATEMENT_LIST
)
1695 append_to_statement_list (tmp
, chain
);
1700 tree_stmt_iterator i
;
1702 i
= tsi_start (*chain
);
1703 tsi_link_before (&i
, expr
, TSI_CONTINUE_LINKING
);
1706 append_to_statement_list (expr
, chain
);
1713 /* Add a statement at the end of a block. */
1716 gfc_add_expr_to_block (stmtblock_t
* block
, tree expr
)
1719 add_expr_to_chain (&block
->head
, expr
, false);
1723 /* Add a statement at the beginning of a block. */
1726 gfc_prepend_expr_to_block (stmtblock_t
* block
, tree expr
)
1729 add_expr_to_chain (&block
->head
, expr
, true);
1733 /* Add a block the end of a block. */
1736 gfc_add_block_to_block (stmtblock_t
* block
, stmtblock_t
* append
)
1738 gcc_assert (append
);
1739 gcc_assert (!append
->has_scope
);
1741 gfc_add_expr_to_block (block
, append
->head
);
1742 append
->head
= NULL_TREE
;
1746 /* Save the current locus. The structure may not be complete, and should
1747 only be used with gfc_restore_backend_locus. */
1750 gfc_save_backend_locus (locus
* loc
)
1752 loc
->lb
= XCNEW (gfc_linebuf
);
1753 loc
->lb
->location
= input_location
;
1754 loc
->lb
->file
= gfc_current_backend_file
;
1758 /* Set the current locus. */
1761 gfc_set_backend_locus (locus
* loc
)
1763 gfc_current_backend_file
= loc
->lb
->file
;
1764 input_location
= loc
->lb
->location
;
1768 /* Restore the saved locus. Only used in conjunction with
1769 gfc_save_backend_locus, to free the memory when we are done. */
1772 gfc_restore_backend_locus (locus
* loc
)
1774 gfc_set_backend_locus (loc
);
1779 /* Translate an executable statement. The tree cond is used by gfc_trans_do.
1780 This static function is wrapped by gfc_trans_code_cond and
1784 trans_code (gfc_code
* code
, tree cond
)
1790 return build_empty_stmt (input_location
);
1792 gfc_start_block (&block
);
1794 /* Translate statements one by one into GENERIC trees until we reach
1795 the end of this gfc_code branch. */
1796 for (; code
; code
= code
->next
)
1798 if (code
->here
!= 0)
1800 res
= gfc_trans_label_here (code
);
1801 gfc_add_expr_to_block (&block
, res
);
1804 gfc_current_locus
= code
->loc
;
1805 gfc_set_backend_locus (&code
->loc
);
1810 case EXEC_END_BLOCK
:
1811 case EXEC_END_NESTED_BLOCK
:
1812 case EXEC_END_PROCEDURE
:
1817 res
= gfc_trans_assign (code
);
1820 case EXEC_LABEL_ASSIGN
:
1821 res
= gfc_trans_label_assign (code
);
1824 case EXEC_POINTER_ASSIGN
:
1825 res
= gfc_trans_pointer_assign (code
);
1828 case EXEC_INIT_ASSIGN
:
1829 if (code
->expr1
->ts
.type
== BT_CLASS
)
1830 res
= gfc_trans_class_init_assign (code
);
1832 res
= gfc_trans_init_assign (code
);
1840 res
= gfc_trans_critical (code
);
1844 res
= gfc_trans_cycle (code
);
1848 res
= gfc_trans_exit (code
);
1852 res
= gfc_trans_goto (code
);
1856 res
= gfc_trans_entry (code
);
1860 res
= gfc_trans_pause (code
);
1864 case EXEC_ERROR_STOP
:
1865 res
= gfc_trans_stop (code
, code
->op
== EXEC_ERROR_STOP
);
1869 /* For MVBITS we've got the special exception that we need a
1870 dependency check, too. */
1872 bool is_mvbits
= false;
1874 if (code
->resolved_isym
)
1876 res
= gfc_conv_intrinsic_subroutine (code
);
1877 if (res
!= NULL_TREE
)
1881 if (code
->resolved_isym
1882 && code
->resolved_isym
->id
== GFC_ISYM_MVBITS
)
1885 res
= gfc_trans_call (code
, is_mvbits
, NULL_TREE
,
1891 res
= gfc_trans_call (code
, false, NULL_TREE
,
1895 case EXEC_ASSIGN_CALL
:
1896 res
= gfc_trans_call (code
, true, NULL_TREE
,
1901 res
= gfc_trans_return (code
);
1905 res
= gfc_trans_if (code
);
1908 case EXEC_ARITHMETIC_IF
:
1909 res
= gfc_trans_arithmetic_if (code
);
1913 res
= gfc_trans_block_construct (code
);
1917 res
= gfc_trans_do (code
, cond
);
1920 case EXEC_DO_CONCURRENT
:
1921 res
= gfc_trans_do_concurrent (code
);
1925 res
= gfc_trans_do_while (code
);
1929 res
= gfc_trans_select (code
);
1932 case EXEC_SELECT_TYPE
:
1933 res
= gfc_trans_select_type (code
);
1937 res
= gfc_trans_flush (code
);
1941 case EXEC_SYNC_IMAGES
:
1942 case EXEC_SYNC_MEMORY
:
1943 res
= gfc_trans_sync (code
, code
->op
);
1948 res
= gfc_trans_lock_unlock (code
, code
->op
);
1951 case EXEC_EVENT_POST
:
1952 case EXEC_EVENT_WAIT
:
1953 res
= gfc_trans_event_post_wait (code
, code
->op
);
1957 res
= gfc_trans_forall (code
);
1961 res
= gfc_trans_where (code
);
1965 res
= gfc_trans_allocate (code
);
1968 case EXEC_DEALLOCATE
:
1969 res
= gfc_trans_deallocate (code
);
1973 res
= gfc_trans_open (code
);
1977 res
= gfc_trans_close (code
);
1981 res
= gfc_trans_read (code
);
1985 res
= gfc_trans_write (code
);
1989 res
= gfc_trans_iolength (code
);
1992 case EXEC_BACKSPACE
:
1993 res
= gfc_trans_backspace (code
);
1997 res
= gfc_trans_endfile (code
);
2001 res
= gfc_trans_inquire (code
);
2005 res
= gfc_trans_wait (code
);
2009 res
= gfc_trans_rewind (code
);
2013 res
= gfc_trans_transfer (code
);
2017 res
= gfc_trans_dt_end (code
);
2020 case EXEC_OMP_ATOMIC
:
2021 case EXEC_OMP_BARRIER
:
2022 case EXEC_OMP_CANCEL
:
2023 case EXEC_OMP_CANCELLATION_POINT
:
2024 case EXEC_OMP_CRITICAL
:
2025 case EXEC_OMP_DISTRIBUTE
:
2026 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO
:
2027 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD
:
2028 case EXEC_OMP_DISTRIBUTE_SIMD
:
2030 case EXEC_OMP_DO_SIMD
:
2031 case EXEC_OMP_FLUSH
:
2032 case EXEC_OMP_MASTER
:
2033 case EXEC_OMP_ORDERED
:
2034 case EXEC_OMP_PARALLEL
:
2035 case EXEC_OMP_PARALLEL_DO
:
2036 case EXEC_OMP_PARALLEL_DO_SIMD
:
2037 case EXEC_OMP_PARALLEL_SECTIONS
:
2038 case EXEC_OMP_PARALLEL_WORKSHARE
:
2039 case EXEC_OMP_SECTIONS
:
2041 case EXEC_OMP_SINGLE
:
2042 case EXEC_OMP_TARGET
:
2043 case EXEC_OMP_TARGET_DATA
:
2044 case EXEC_OMP_TARGET_ENTER_DATA
:
2045 case EXEC_OMP_TARGET_EXIT_DATA
:
2046 case EXEC_OMP_TARGET_PARALLEL
:
2047 case EXEC_OMP_TARGET_PARALLEL_DO
:
2048 case EXEC_OMP_TARGET_PARALLEL_DO_SIMD
:
2049 case EXEC_OMP_TARGET_SIMD
:
2050 case EXEC_OMP_TARGET_TEAMS
:
2051 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE
:
2052 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO
:
2053 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD
:
2054 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD
:
2055 case EXEC_OMP_TARGET_UPDATE
:
2057 case EXEC_OMP_TASKGROUP
:
2058 case EXEC_OMP_TASKLOOP
:
2059 case EXEC_OMP_TASKLOOP_SIMD
:
2060 case EXEC_OMP_TASKWAIT
:
2061 case EXEC_OMP_TASKYIELD
:
2062 case EXEC_OMP_TEAMS
:
2063 case EXEC_OMP_TEAMS_DISTRIBUTE
:
2064 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO
:
2065 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD
:
2066 case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD
:
2067 case EXEC_OMP_WORKSHARE
:
2068 res
= gfc_trans_omp_directive (code
);
2071 case EXEC_OACC_CACHE
:
2072 case EXEC_OACC_WAIT
:
2073 case EXEC_OACC_UPDATE
:
2074 case EXEC_OACC_LOOP
:
2075 case EXEC_OACC_HOST_DATA
:
2076 case EXEC_OACC_DATA
:
2077 case EXEC_OACC_KERNELS
:
2078 case EXEC_OACC_KERNELS_LOOP
:
2079 case EXEC_OACC_PARALLEL
:
2080 case EXEC_OACC_PARALLEL_LOOP
:
2081 case EXEC_OACC_ENTER_DATA
:
2082 case EXEC_OACC_EXIT_DATA
:
2083 case EXEC_OACC_ATOMIC
:
2084 case EXEC_OACC_DECLARE
:
2085 res
= gfc_trans_oacc_directive (code
);
2089 gfc_internal_error ("gfc_trans_code(): Bad statement code");
2092 gfc_set_backend_locus (&code
->loc
);
2094 if (res
!= NULL_TREE
&& ! IS_EMPTY_STMT (res
))
2096 if (TREE_CODE (res
) != STATEMENT_LIST
)
2097 SET_EXPR_LOCATION (res
, input_location
);
2099 /* Add the new statement to the block. */
2100 gfc_add_expr_to_block (&block
, res
);
2104 /* Return the finished block. */
2105 return gfc_finish_block (&block
);
2109 /* Translate an executable statement with condition, cond. The condition is
2110 used by gfc_trans_do to test for IO result conditions inside implied
2111 DO loops of READ and WRITE statements. See build_dt in trans-io.c. */
2114 gfc_trans_code_cond (gfc_code
* code
, tree cond
)
2116 return trans_code (code
, cond
);
2119 /* Translate an executable statement without condition. */
2122 gfc_trans_code (gfc_code
* code
)
2124 return trans_code (code
, NULL_TREE
);
2128 /* This function is called after a complete program unit has been parsed
2132 gfc_generate_code (gfc_namespace
* ns
)
2135 if (ns
->is_block_data
)
2137 gfc_generate_block_data (ns
);
2141 gfc_generate_function_code (ns
);
2145 /* This function is called after a complete module has been parsed
2149 gfc_generate_module_code (gfc_namespace
* ns
)
2152 struct module_htab_entry
*entry
;
2154 gcc_assert (ns
->proc_name
->backend_decl
== NULL
);
2155 ns
->proc_name
->backend_decl
2156 = build_decl (ns
->proc_name
->declared_at
.lb
->location
,
2157 NAMESPACE_DECL
, get_identifier (ns
->proc_name
->name
),
2159 entry
= gfc_find_module (ns
->proc_name
->name
);
2160 if (entry
->namespace_decl
)
2161 /* Buggy sourcecode, using a module before defining it? */
2162 entry
->decls
->empty ();
2163 entry
->namespace_decl
= ns
->proc_name
->backend_decl
;
2165 gfc_generate_module_vars (ns
);
2167 /* We need to generate all module function prototypes first, to allow
2169 for (n
= ns
->contained
; n
; n
= n
->sibling
)
2176 gfc_create_function_decl (n
, false);
2177 DECL_CONTEXT (n
->proc_name
->backend_decl
) = ns
->proc_name
->backend_decl
;
2178 gfc_module_add_decl (entry
, n
->proc_name
->backend_decl
);
2179 for (el
= ns
->entries
; el
; el
= el
->next
)
2181 DECL_CONTEXT (el
->sym
->backend_decl
) = ns
->proc_name
->backend_decl
;
2182 gfc_module_add_decl (entry
, el
->sym
->backend_decl
);
2186 for (n
= ns
->contained
; n
; n
= n
->sibling
)
2191 gfc_generate_function_code (n
);
2196 /* Initialize an init/cleanup block with existing code. */
2199 gfc_start_wrapped_block (gfc_wrapped_block
* block
, tree code
)
2203 block
->init
= NULL_TREE
;
2205 block
->cleanup
= NULL_TREE
;
2209 /* Add a new pair of initializers/clean-up code. */
2212 gfc_add_init_cleanup (gfc_wrapped_block
* block
, tree init
, tree cleanup
)
2216 /* The new pair of init/cleanup should be "wrapped around" the existing
2217 block of code, thus the initialization is added to the front and the
2218 cleanup to the back. */
2219 add_expr_to_chain (&block
->init
, init
, true);
2220 add_expr_to_chain (&block
->cleanup
, cleanup
, false);
2224 /* Finish up a wrapped block by building a corresponding try-finally expr. */
2227 gfc_finish_wrapped_block (gfc_wrapped_block
* block
)
2233 /* Build the final expression. For this, just add init and body together,
2234 and put clean-up with that into a TRY_FINALLY_EXPR. */
2235 result
= block
->init
;
2236 add_expr_to_chain (&result
, block
->code
, false);
2238 result
= build2_loc (input_location
, TRY_FINALLY_EXPR
, void_type_node
,
2239 result
, block
->cleanup
);
2241 /* Clear the block. */
2242 block
->init
= NULL_TREE
;
2243 block
->code
= NULL_TREE
;
2244 block
->cleanup
= NULL_TREE
;
2250 /* Helper function for marking a boolean expression tree as unlikely. */
2253 gfc_unlikely (tree cond
, enum br_predictor predictor
)
2259 cond
= fold_convert (long_integer_type_node
, cond
);
2260 tmp
= build_zero_cst (long_integer_type_node
);
2261 cond
= build_call_expr_loc (input_location
,
2262 builtin_decl_explicit (BUILT_IN_EXPECT
),
2264 build_int_cst (integer_type_node
,
2267 cond
= fold_convert (boolean_type_node
, cond
);
2272 /* Helper function for marking a boolean expression tree as likely. */
2275 gfc_likely (tree cond
, enum br_predictor predictor
)
2281 cond
= fold_convert (long_integer_type_node
, cond
);
2282 tmp
= build_one_cst (long_integer_type_node
);
2283 cond
= build_call_expr_loc (input_location
,
2284 builtin_decl_explicit (BUILT_IN_EXPECT
),
2286 build_int_cst (integer_type_node
,
2289 cond
= fold_convert (boolean_type_node
, cond
);
2294 /* Get the string length for a deferred character length component. */
2297 gfc_deferred_strlen (gfc_component
*c
, tree
*decl
)
2299 char name
[GFC_MAX_SYMBOL_LEN
+9];
2300 gfc_component
*strlen
;
2301 if (!(c
->ts
.type
== BT_CHARACTER
&& c
->ts
.deferred
))
2303 sprintf (name
, "_%s_length", c
->name
);
2304 for (strlen
= c
; strlen
; strlen
= strlen
->next
)
2305 if (strcmp (strlen
->name
, name
) == 0)
2307 *decl
= strlen
? strlen
->backend_decl
: NULL_TREE
;
2308 return strlen
!= NULL
;