diff options
Diffstat (limited to 'gcc/fortran/trans-array.c')
-rw-r--r-- | gcc/fortran/trans-array.c | 448 |
1 files changed, 358 insertions, 90 deletions
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c index 1708f7c..803462a4 100644 --- a/gcc/fortran/trans-array.c +++ b/gcc/fortran/trans-array.c @@ -5633,12 +5633,13 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree status, tree errmsg, tree gfc_array_deallocate (tree descriptor, tree pstat, tree errmsg, tree errlen, - tree label_finish, gfc_expr* expr) + tree label_finish, gfc_expr* expr, + int coarray_dealloc_mode) { tree var; tree tmp; stmtblock_t block; - bool coarray = gfc_caf_attr (expr).codimension; + bool coarray = coarray_dealloc_mode != GFC_CAF_COARRAY_NOCOARRAY; gfc_start_block (&block); @@ -5648,7 +5649,8 @@ gfc_array_deallocate (tree descriptor, tree pstat, tree errmsg, tree errlen, /* Parameter is the address of the data component. */ tmp = gfc_deallocate_with_status (coarray ? descriptor : var, pstat, errmsg, - errlen, label_finish, false, expr, coarray); + errlen, label_finish, false, expr, + coarray_dealloc_mode); gfc_add_expr_to_block (&block, tmp); /* Zero the data pointer; only for coarrays an error can occur and then @@ -7782,11 +7784,13 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, bool g77, /* Generate code to deallocate an array, if it is allocated. */ tree -gfc_trans_dealloc_allocated (tree descriptor, bool coarray, gfc_expr *expr) +gfc_trans_dealloc_allocated (tree descriptor, gfc_expr *expr, + int coarray_dealloc_mode) { tree tmp; tree var; stmtblock_t block; + bool coarray = coarray_dealloc_mode != GFC_CAF_COARRAY_NOCOARRAY; gfc_start_block (&block); @@ -7797,8 +7801,8 @@ gfc_trans_dealloc_allocated (tree descriptor, bool coarray, gfc_expr *expr) Although it is ignored here, it's presence ensures that arrays that are already deallocated are ignored. */ tmp = gfc_deallocate_with_status (coarray ? descriptor : var, NULL_TREE, - NULL_TREE, NULL_TREE, NULL_TREE, true, - expr, coarray); + NULL_TREE, NULL_TREE, NULL_TREE, true, expr, + coarray_dealloc_mode); gfc_add_expr_to_block (&block, tmp); /* Zero the data pointer. */ @@ -7855,9 +7859,7 @@ duplicate_allocatable (tree dest, tree src, tree type, int rank, if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (dest))) { - tmp = null_pointer_node; - tmp = fold_build2_loc (input_location, MODIFY_EXPR, type, dest, tmp); - gfc_add_expr_to_block (&block, tmp); + gfc_add_modify (&block, dest, fold_convert (type, null_pointer_node)); null_data = gfc_finish_block (&block); gfc_init_block (&block); @@ -7869,9 +7871,7 @@ duplicate_allocatable (tree dest, tree src, tree type, int rank, if (!no_malloc) { tmp = gfc_call_malloc (&block, type, size); - tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node, - dest, fold_convert (type, tmp)); - gfc_add_expr_to_block (&block, tmp); + gfc_add_modify (&block, dest, fold_convert (type, tmp)); } if (!no_memcpy) @@ -7967,17 +7967,152 @@ gfc_duplicate_allocatable_nocopy (tree dest, tree src, tree type, int rank) } +static tree +duplicate_allocatable_coarray (tree dest, tree dest_tok, tree src, + tree type, int rank) +{ + tree tmp; + tree size; + tree nelems; + tree null_cond; + tree null_data; + stmtblock_t block, globalblock; + + /* If the source is null, set the destination to null. Then, + allocate memory to the destination. */ + gfc_init_block (&block); + gfc_init_block (&globalblock); + + if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (dest))) + { + gfc_se se; + symbol_attribute attr; + tree dummy_desc; + + gfc_init_se (&se, NULL); + dummy_desc = gfc_conv_scalar_to_descriptor (&se, dest, attr); + gfc_add_block_to_block (&globalblock, &se.pre); + size = TYPE_SIZE_UNIT (TREE_TYPE (type)); + + gfc_add_modify (&block, dest, fold_convert (type, null_pointer_node)); + gfc_allocate_using_caf_lib (&block, dummy_desc, size, + gfc_build_addr_expr (NULL_TREE, dest_tok), + NULL_TREE, NULL_TREE, NULL_TREE, + GFC_CAF_COARRAY_ALLOC_REGISTER_ONLY); + null_data = gfc_finish_block (&block); + + gfc_init_block (&block); + + gfc_allocate_using_caf_lib (&block, dummy_desc, + fold_convert (size_type_node, size), + gfc_build_addr_expr (NULL_TREE, dest_tok), + NULL_TREE, NULL_TREE, NULL_TREE, + GFC_CAF_COARRAY_ALLOC); + + tmp = builtin_decl_explicit (BUILT_IN_MEMCPY); + tmp = build_call_expr_loc (input_location, tmp, 3, dest, src, + fold_convert (size_type_node, size)); + gfc_add_expr_to_block (&block, tmp); + } + else + { + /* Set the rank or unitialized memory access may be reported. */ + tmp = gfc_conv_descriptor_dtype (dest); + gfc_add_modify (&globalblock, tmp, build_int_cst (TREE_TYPE (tmp), rank)); + + if (rank) + nelems = gfc_full_array_size (&block, src, rank); + else + nelems = integer_one_node; + + tmp = fold_convert (size_type_node, + TYPE_SIZE_UNIT (gfc_get_element_type (type))); + size = fold_build2_loc (input_location, MULT_EXPR, size_type_node, + fold_convert (size_type_node, nelems), tmp); + + gfc_conv_descriptor_data_set (&block, dest, null_pointer_node); + gfc_allocate_using_caf_lib (&block, dest, fold_convert (size_type_node, + size), + gfc_build_addr_expr (NULL_TREE, dest_tok), + NULL_TREE, NULL_TREE, NULL_TREE, + GFC_CAF_COARRAY_ALLOC_REGISTER_ONLY); + null_data = gfc_finish_block (&block); + + gfc_init_block (&block); + gfc_allocate_using_caf_lib (&block, dest, + fold_convert (size_type_node, size), + gfc_build_addr_expr (NULL_TREE, dest_tok), + NULL_TREE, NULL_TREE, NULL_TREE, + GFC_CAF_COARRAY_ALLOC); + + tmp = builtin_decl_explicit (BUILT_IN_MEMCPY); + tmp = build_call_expr_loc (input_location, tmp, 3, + gfc_conv_descriptor_data_get (dest), + gfc_conv_descriptor_data_get (src), + fold_convert (size_type_node, size)); + gfc_add_expr_to_block (&block, tmp); + } + + tmp = gfc_finish_block (&block); + + /* Null the destination if the source is null; otherwise do + the register and copy. */ + if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (src))) + null_cond = src; + else + null_cond = gfc_conv_descriptor_data_get (src); + + null_cond = convert (pvoid_type_node, null_cond); + null_cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, + null_cond, null_pointer_node); + gfc_add_expr_to_block (&globalblock, build3_v (COND_EXPR, null_cond, tmp, + null_data)); + return gfc_finish_block (&globalblock); +} + + +/* Helper function to abstract whether coarray processing is enabled. */ + +static bool +caf_enabled (int caf_mode) +{ + return (caf_mode & GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY) + == GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY; +} + + +/* Helper function to abstract whether coarray processing is enabled + and we are in a derived type coarray. */ + +static bool +caf_in_coarray (int caf_mode) +{ + static const int pat = GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY + | GFC_STRUCTURE_CAF_MODE_IN_COARRAY; + return (caf_mode & pat) == pat; +} + + +/* Helper function to abstract whether coarray is to deallocate only. */ + +bool +gfc_caf_is_dealloc_only (int caf_mode) +{ + return (caf_mode & GFC_STRUCTURE_CAF_MODE_DEALLOC_ONLY) + == GFC_STRUCTURE_CAF_MODE_DEALLOC_ONLY; +} + + /* Recursively traverse an object of derived type, generating code to deallocate, nullify or copy allocatable components. This is the work horse function for the functions named in this enum. */ -enum {DEALLOCATE_ALLOC_COMP = 1, DEALLOCATE_ALLOC_COMP_NO_CAF, - NULLIFY_ALLOC_COMP, COPY_ALLOC_COMP, COPY_ONLY_ALLOC_COMP, - COPY_ALLOC_COMP_CAF}; +enum {DEALLOCATE_ALLOC_COMP = 1, NULLIFY_ALLOC_COMP, + COPY_ALLOC_COMP, COPY_ONLY_ALLOC_COMP, REASSIGN_CAF_COMP}; static tree structure_alloc_comps (gfc_symbol * der_type, tree decl, - tree dest, int rank, int purpose) + tree dest, int rank, int purpose, int caf_mode) { gfc_component *c; gfc_loopinfo loop; @@ -8011,10 +8146,10 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, /* Deref dest in sync with decl, but only when it is not NULL. */ if (dest) dest = build_fold_indirect_ref_loc (input_location, dest); - } - /* Just in case it gets dereferenced. */ - decl_type = TREE_TYPE (decl); + /* Update the decl_type because it got dereferenced. */ + decl_type = TREE_TYPE (decl); + } /* If this is an array of derived types with allocatable components build a loop and recursively call this function. */ @@ -8056,16 +8191,18 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, vref = gfc_build_array_ref (var, index, NULL); - if (purpose == COPY_ALLOC_COMP || purpose == COPY_ONLY_ALLOC_COMP) - { + if ((purpose == COPY_ALLOC_COMP || purpose == COPY_ONLY_ALLOC_COMP) + && !caf_enabled (caf_mode)) + { tmp = build_fold_indirect_ref_loc (input_location, gfc_conv_array_data (dest)); dref = gfc_build_array_ref (tmp, index, NULL); tmp = structure_alloc_comps (der_type, vref, dref, rank, - COPY_ALLOC_COMP); + COPY_ALLOC_COMP, 0); } else - tmp = structure_alloc_comps (der_type, vref, NULL_TREE, rank, purpose); + tmp = structure_alloc_comps (der_type, vref, NULL_TREE, rank, purpose, + caf_mode); gfc_add_expr_to_block (&loopbody, tmp); @@ -8111,7 +8248,6 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, switch (purpose) { case DEALLOCATE_ALLOC_COMP: - case DEALLOCATE_ALLOC_COMP_NO_CAF: /* gfc_deallocate_scalar_with_status calls gfc_deallocate_alloc_comp (i.e. this function) so generate all the calls and suppress the @@ -8128,21 +8264,57 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, /* The finalizer frees allocatable components. */ called_dealloc_with_status = gfc_add_comp_finalizer_call (&tmpblock, comp, c, - purpose == DEALLOCATE_ALLOC_COMP); + purpose == DEALLOCATE_ALLOC_COMP + && caf_enabled (caf_mode)); } else comp = NULL_TREE; - if (c->attr.allocatable && !c->attr.proc_pointer + if (c->attr.allocatable && !c->attr.proc_pointer && !same_type && (c->attr.dimension - || (c->attr.codimension - && purpose != DEALLOCATE_ALLOC_COMP_NO_CAF)) - && !same_type) + || (caf_enabled (caf_mode) + && (caf_in_coarray (caf_mode) || c->attr.codimension)))) { + /* Allocatable arrays or coarray'ed components (scalar or + array). */ + int caf_dereg_mode + = (caf_in_coarray (caf_mode) || c->attr.codimension) + ? (gfc_caf_is_dealloc_only (caf_mode) + ? GFC_CAF_COARRAY_DEALLOCATE_ONLY + : GFC_CAF_COARRAY_DEREGISTER) + : GFC_CAF_COARRAY_NOCOARRAY; if (comp == NULL_TREE) comp = fold_build3_loc (input_location, COMPONENT_REF, ctype, decl, cdecl, NULL_TREE); - tmp = gfc_trans_dealloc_allocated (comp, c->attr.codimension, NULL); + + if (c->attr.dimension || c->attr.codimension) + /* Deallocate array. */ + tmp = gfc_trans_dealloc_allocated (comp, NULL, caf_dereg_mode); + else + { + /* Deallocate scalar. */ + tree cond = fold_build2_loc (input_location, NE_EXPR, + boolean_type_node, comp, + build_int_cst (TREE_TYPE (comp), + 0)); + + tmp = fold_build3_loc (input_location, COMPONENT_REF, + pvoid_type_node, decl, c->caf_token, + NULL_TREE); + tmp = build_call_expr_loc (input_location, + gfor_fndecl_caf_deregister, 5, + gfc_build_addr_expr (NULL_TREE, + tmp), + build_int_cst (integer_type_node, + caf_dereg_mode), + null_pointer_node, + null_pointer_node, + integer_zero_node); + tmp = fold_build3_loc (input_location, COND_EXPR, + void_type_node, cond, tmp, + build_empty_stmt (input_location)); + } + gfc_add_expr_to_block (&tmpblock, tmp); } else if (c->attr.allocatable && !c->attr.codimension && !same_type) @@ -8152,7 +8324,8 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, comp = fold_build3_loc (input_location, COMPONENT_REF, ctype, decl, cdecl, NULL_TREE); - tmp = gfc_deallocate_scalar_with_status (comp, NULL, true, NULL, + tmp = gfc_deallocate_scalar_with_status (comp, NULL_TREE, + NULL_TREE, true, NULL, c->ts); gfc_add_expr_to_block (&tmpblock, tmp); called_dealloc_with_status = true; @@ -8168,8 +8341,6 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, tree is_allocated; tree ubound; tree cdesc; - tree zero = build_int_cst (gfc_array_index_type, 0); - tree unity = build_int_cst (gfc_array_index_type, 1); tree data; stmtblock_t dealloc_block; @@ -8191,8 +8362,8 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, ubound = build_int_cst (gfc_array_index_type, 1); } - cdesc = gfc_get_array_type_bounds (tmp, 1, 0, - &unity, &ubound, 1, + cdesc = gfc_get_array_type_bounds (tmp, 1, 0, &gfc_index_one_node, + &ubound, 1, GFC_ARRAY_ALLOCATABLE, false); cdesc = gfc_create_var (cdesc, "cdesc"); @@ -8201,11 +8372,13 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, gfc_add_modify (&dealloc_block, gfc_conv_descriptor_dtype (cdesc), gfc_get_dtype_rank_type (1, tmp)); gfc_conv_descriptor_lbound_set (&dealloc_block, cdesc, - zero, unity); + gfc_index_zero_node, + gfc_index_one_node); gfc_conv_descriptor_stride_set (&dealloc_block, cdesc, - zero, unity); + gfc_index_zero_node, + gfc_index_one_node); gfc_conv_descriptor_ubound_set (&dealloc_block, cdesc, - zero, ubound); + gfc_index_zero_node, ubound); if (c->attr.dimension) data = gfc_conv_descriptor_data_get (comp); @@ -8247,7 +8420,7 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, else if (c->ts.type == BT_CLASS && CLASS_DATA (c)->attr.allocatable && (!CLASS_DATA (c)->attr.codimension - || purpose != DEALLOCATE_ALLOC_COMP_NO_CAF)) + || !caf_enabled (caf_mode))) { /* Allocatable CLASS components. */ @@ -8257,11 +8430,15 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, TREE_TYPE (tmp), comp, tmp, NULL_TREE); if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (comp))) - tmp = gfc_trans_dealloc_allocated (comp, - CLASS_DATA (c)->attr.codimension, NULL); + tmp = gfc_trans_dealloc_allocated (comp, NULL, + CLASS_DATA (c)->attr.codimension + ? GFC_CAF_COARRAY_DEREGISTER + : GFC_CAF_COARRAY_NOCOARRAY); else { - tmp = gfc_deallocate_scalar_with_status (comp, NULL_TREE, true, NULL, + tmp = gfc_deallocate_scalar_with_status (comp, NULL_TREE, + NULL_TREE, true, + NULL, CLASS_DATA (c)->ts); gfc_add_expr_to_block (&tmpblock, tmp); called_dealloc_with_status = true; @@ -8317,7 +8494,7 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, decl, cdecl, NULL_TREE); rank = c->as ? c->as->rank : 0; tmp = structure_alloc_comps (c->ts.u.derived, comp, NULL_TREE, - rank, purpose); + rank, purpose, caf_mode); gfc_add_expr_to_block (&fnblock, tmp); } @@ -8326,14 +8503,20 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, break; case NULLIFY_ALLOC_COMP: - if (c->attr.pointer || c->attr.proc_pointer) + if (c->attr.pointer || c->attr.proc_pointer + || !(c->attr.allocatable || (c->ts.type == BT_CLASS + && CLASS_DATA (c)->attr.allocatable) + || cmp_has_alloc_comps)) continue; - else if (c->attr.allocatable - && (c->attr.dimension|| c->attr.codimension)) + + /* Coarrays need the component to be initialized before the api-call + is made. */ + if (c->attr.allocatable && (c->attr.dimension || c->attr.codimension)) { comp = fold_build3_loc (input_location, COMPONENT_REF, ctype, decl, cdecl, NULL_TREE); gfc_conv_descriptor_data_set (&fnblock, comp, null_pointer_node); + cmp_has_alloc_comps = false; } else if (c->attr.allocatable) { @@ -8354,6 +8537,7 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, build_int_cst (TREE_TYPE (comp), 0)); gfc_add_expr_to_block (&fnblock, tmp); } + cmp_has_alloc_comps = false; } else if (c->ts.type == BT_CLASS && CLASS_DATA (c)->attr.allocatable) { @@ -8371,46 +8555,92 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, build_int_cst (TREE_TYPE (comp), 0)); gfc_add_expr_to_block (&fnblock, tmp); } + cmp_has_alloc_comps = false; + } + + if (flag_coarray == GFC_FCOARRAY_LIB + && (caf_in_coarray (caf_mode) || c->attr.codimension)) + { + /* Register the component with the coarray library. */ + tree token; + + comp = fold_build3_loc (input_location, COMPONENT_REF, ctype, + decl, cdecl, NULL_TREE); + if (c->attr.dimension || c->attr.codimension) + { + tmp = fold_build3_loc (input_location, COMPONENT_REF, ctype, + decl, cdecl, NULL_TREE); + token = gfc_conv_descriptor_token (tmp); + } + else + { + gfc_se se; + symbol_attribute attr; + + gfc_init_se (&se, NULL); + gfc_clear_attr (&attr); + token = fold_build3_loc (input_location, COMPONENT_REF, + pvoid_type_node, decl, c->caf_token, + NULL_TREE); + comp = gfc_conv_scalar_to_descriptor (&se, comp, attr); + gfc_add_block_to_block (&fnblock, &se.pre); + } + + /* NULL the member-token before registering it or uninitialized + memory accesses may occur. */ + gfc_add_modify (&fnblock, token, fold_convert (TREE_TYPE (token), + null_pointer_node)); + gfc_allocate_using_caf_lib (&fnblock, comp, size_zero_node, + gfc_build_addr_expr (NULL_TREE, + token), + NULL_TREE, NULL_TREE, NULL_TREE, + GFC_CAF_COARRAY_ALLOC_REGISTER_ONLY); } - else if (cmp_has_alloc_comps) + + if (cmp_has_alloc_comps) { comp = fold_build3_loc (input_location, COMPONENT_REF, ctype, decl, cdecl, NULL_TREE); rank = c->as ? c->as->rank : 0; tmp = structure_alloc_comps (c->ts.u.derived, comp, NULL_TREE, - rank, purpose); + rank, purpose, caf_mode); gfc_add_expr_to_block (&fnblock, tmp); } break; - case COPY_ALLOC_COMP_CAF: - if (!c->attr.codimension - && (c->ts.type != BT_CLASS || CLASS_DATA (c)->attr.coarray_comp) - && (c->ts.type != BT_DERIVED - || !c->ts.u.derived->attr.coarray_comp)) - continue; - - comp = fold_build3_loc (input_location, COMPONENT_REF, ctype, decl, - cdecl, NULL_TREE); - dcmp = fold_build3_loc (input_location, COMPONENT_REF, ctype, dest, - cdecl, NULL_TREE); - - if (c->attr.codimension) + case REASSIGN_CAF_COMP: + if (caf_enabled (caf_mode) + && (c->attr.codimension + || (c->ts.type == BT_CLASS + && (CLASS_DATA (c)->attr.coarray_comp + || caf_in_coarray (caf_mode))) + || (c->ts.type == BT_DERIVED + && (c->ts.u.derived->attr.coarray_comp + || caf_in_coarray (caf_mode)))) + && !same_type) { - if (c->ts.type == BT_CLASS) + comp = fold_build3_loc (input_location, COMPONENT_REF, ctype, + decl, cdecl, NULL_TREE); + dcmp = fold_build3_loc (input_location, COMPONENT_REF, ctype, + dest, cdecl, NULL_TREE); + + if (c->attr.codimension) { - comp = gfc_class_data_get (comp); - dcmp = gfc_class_data_get (dcmp); - } - gfc_conv_descriptor_data_set (&fnblock, dcmp, + if (c->ts.type == BT_CLASS) + { + comp = gfc_class_data_get (comp); + dcmp = gfc_class_data_get (dcmp); + } + gfc_conv_descriptor_data_set (&fnblock, dcmp, gfc_conv_descriptor_data_get (comp)); - } - else - { - tmp = structure_alloc_comps (c->ts.u.derived, comp, dcmp, - rank, purpose); - gfc_add_expr_to_block (&fnblock, tmp); - + } + else + { + tmp = structure_alloc_comps (c->ts.u.derived, comp, dcmp, + rank, purpose, caf_mode + | GFC_STRUCTURE_CAF_MODE_IN_COARRAY); + gfc_add_expr_to_block (&fnblock, tmp); + } } break; @@ -8503,7 +8733,8 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, gfc_add_modify (&fnblock, dcmp, tmp); add_when_allocated = structure_alloc_comps (c->ts.u.derived, comp, dcmp, - rank, purpose); + rank, purpose, + caf_mode); } else add_when_allocated = NULL_TREE; @@ -8530,11 +8761,24 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, gfc_add_expr_to_block (&fnblock, tmp); } else if (c->attr.allocatable && !c->attr.proc_pointer && !same_type - && (!(cmp_has_alloc_comps && c->as) || c->attr.codimension)) + && (!(cmp_has_alloc_comps && c->as) || c->attr.codimension + || caf_in_coarray (caf_mode))) { rank = c->as ? c->as->rank : 0; if (c->attr.codimension) tmp = gfc_copy_allocatable_data (dcmp, comp, ctype, rank); + else if (flag_coarray == GFC_FCOARRAY_LIB + && caf_in_coarray (caf_mode)) + { + tree dst_tok = c->as ? gfc_conv_descriptor_token (dcmp) + : fold_build3_loc (input_location, + COMPONENT_REF, + pvoid_type_node, dest, + c->caf_token, + NULL_TREE); + tmp = duplicate_allocatable_coarray (dcmp, dst_tok, comp, + ctype, rank); + } else tmp = gfc_duplicate_allocatable (dcmp, comp, ctype, rank, add_when_allocated); @@ -8562,7 +8806,8 @@ tree gfc_nullify_alloc_comp (gfc_symbol * der_type, tree decl, int rank) { return structure_alloc_comps (der_type, decl, NULL_TREE, rank, - NULLIFY_ALLOC_COMP); + NULLIFY_ALLOC_COMP, + GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY); } @@ -8570,10 +8815,12 @@ gfc_nullify_alloc_comp (gfc_symbol * der_type, tree decl, int rank) deallocate allocatable components. */ tree -gfc_deallocate_alloc_comp (gfc_symbol * der_type, tree decl, int rank) +gfc_deallocate_alloc_comp (gfc_symbol * der_type, tree decl, int rank, + int caf_mode) { return structure_alloc_comps (der_type, decl, NULL_TREE, rank, - DEALLOCATE_ALLOC_COMP); + DEALLOCATE_ALLOC_COMP, + GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY | caf_mode); } @@ -8586,14 +8833,15 @@ tree gfc_deallocate_alloc_comp_no_caf (gfc_symbol * der_type, tree decl, int rank) { return structure_alloc_comps (der_type, decl, NULL_TREE, rank, - DEALLOCATE_ALLOC_COMP_NO_CAF); + DEALLOCATE_ALLOC_COMP, 0); } tree gfc_reassign_alloc_comp_caf (gfc_symbol *der_type, tree decl, tree dest) { - return structure_alloc_comps (der_type, decl, dest, 0, COPY_ALLOC_COMP_CAF); + return structure_alloc_comps (der_type, decl, dest, 0, REASSIGN_CAF_COMP, + GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY); } @@ -8601,9 +8849,11 @@ gfc_reassign_alloc_comp_caf (gfc_symbol *der_type, tree decl, tree dest) copy it and its allocatable components. */ tree -gfc_copy_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank) +gfc_copy_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank, + int caf_mode) { - return structure_alloc_comps (der_type, decl, dest, rank, COPY_ALLOC_COMP); + return structure_alloc_comps (der_type, decl, dest, rank, COPY_ALLOC_COMP, + caf_mode); } @@ -8613,7 +8863,8 @@ gfc_copy_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank) tree gfc_copy_only_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank) { - return structure_alloc_comps (der_type, decl, dest, rank, COPY_ONLY_ALLOC_COMP); + return structure_alloc_comps (der_type, decl, dest, rank, + COPY_ONLY_ALLOC_COMP, 0); } @@ -9205,15 +9456,17 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop, else { tmp = build_call_expr_loc (input_location, - gfor_fndecl_caf_deregister, - 4, token, null_pointer_node, - null_pointer_node, integer_zero_node); + gfor_fndecl_caf_deregister, 5, token, + build_int_cst (integer_type_node, + GFC_CAF_COARRAY_DEALLOCATE_ONLY), + null_pointer_node, null_pointer_node, + integer_zero_node); gfc_add_expr_to_block (&realloc_block, tmp); tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_register, 7, size2, build_int_cst (integer_type_node, - GFC_CAF_COARRAY_ALLOC), + GFC_CAF_COARRAY_ALLOC_ALLOCATE_ONLY), token, gfc_build_addr_expr (NULL_TREE, desc), null_pointer_node, null_pointer_node, integer_zero_node); @@ -9398,7 +9651,20 @@ gfc_trans_deferred_array (gfc_symbol * sym, gfc_wrapped_block * block) /* NULLIFY the data pointer, for non-saved allocatables. */ if (GFC_DESCRIPTOR_TYPE_P (type) && !sym->attr.save && sym->attr.allocatable) - gfc_conv_descriptor_data_set (&init, descriptor, null_pointer_node); + { + gfc_conv_descriptor_data_set (&init, descriptor, null_pointer_node); + if (flag_coarray == GFC_FCOARRAY_LIB && sym->attr.codimension) + { + /* Declare the variable static so its array descriptor stays present + after leaving the scope. It may still be accessed through another + image. This may happen, for example, with the caf_mpi + implementation. */ + TREE_STATIC (descriptor) = 1; + tmp = gfc_conv_descriptor_token (descriptor); + gfc_add_modify (&init, tmp, fold_convert (TREE_TYPE (tmp), + null_pointer_node)); + } + } gfc_restore_backend_locus (&loc); gfc_init_block (&cleanup); @@ -9432,8 +9698,10 @@ gfc_trans_deferred_array (gfc_symbol * sym, gfc_wrapped_block * block) { gfc_expr *e; e = has_finalizer ? gfc_lval_expr_from_sym (sym) : NULL; - tmp = gfc_trans_dealloc_allocated (sym->backend_decl, - sym->attr.codimension, e); + tmp = gfc_trans_dealloc_allocated (sym->backend_decl, e, + sym->attr.codimension + ? GFC_CAF_COARRAY_DEREGISTER + : GFC_CAF_COARRAY_NOCOARRAY); if (e) gfc_free_expr (e); gfc_add_expr_to_block (&cleanup, tmp); |