diff options
author | Andre Vehreschild <vehre@gcc.gnu.org> | 2015-10-25 13:28:57 +0100 |
---|---|---|
committer | Andre Vehreschild <vehre@gcc.gnu.org> | 2015-10-25 13:28:57 +0100 |
commit | b8ac4f3b22887143eec7e51497e95ff7301631df (patch) | |
tree | 2bf4d8a03141715e2374e096c4386e41791de20e /gcc/fortran/trans-expr.c | |
parent | f63df1373912b1c8b65e34e064594c0eb15153f9 (diff) | |
download | gcc-b8ac4f3b22887143eec7e51497e95ff7301631df.zip gcc-b8ac4f3b22887143eec7e51497e95ff7301631df.tar.gz gcc-b8ac4f3b22887143eec7e51497e95ff7301631df.tar.bz2 |
re PR fortran/66927 (ICE in gfc_conf_procedure_call)
gcc/fortran/ChangeLog:
2015-10-25 Andre Vehreschild <vehre@gcc.gnu.org>
PR fortran/66927
PR fortran/67044
* trans-array.c (build_array_ref): Modified call to
gfc_get_class_array_ref to adhere to new interface.
(gfc_conv_expr_descriptor): For one-based arrays that
are filled by a loop starting at one the start index of the
source array has to be mangled into the offset.
* trans-expr.c (gfc_get_class_array_ref): When the tree to get
the _data component is present already, add a way to supply it.
(gfc_copy_class_to_class): Allow to copy to a derived type also.
* trans-stmt.c (gfc_trans_allocate): Do not conv_expr_descriptor
for functions returning a class or derived object. Get the
reference instead.
* trans.h: Interface change of gfc_get_class_array_ref.
gcc/testsuite/ChangeLog:
2015-10-25 Andre Vehreschild <vehre@gmx.de>
PR fortran/66927
PR fortran/67044
* gfortran.dg/allocate_with_source_10.f08: New test.
* gfortran.dg/allocate_with_source_11.f08: New test.
* gfortran.dg/class_array_15.f03: Changed count of expected
_builtin_frees to 11. One step of temporaries is spared, therefore
the allocatable component of that temporary is not to be freeed.
From-SVN: r229294
Diffstat (limited to 'gcc/fortran/trans-expr.c')
-rw-r--r-- | gcc/fortran/trans-expr.c | 49 |
1 files changed, 39 insertions, 10 deletions
diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c index 2f42c04..9585de6 100644 --- a/gcc/fortran/trans-expr.c +++ b/gcc/fortran/trans-expr.c @@ -1039,9 +1039,10 @@ gfc_conv_class_to_class (gfc_se *parmse, gfc_expr *e, gfc_typespec class_ts, of the referenced element. */ tree -gfc_get_class_array_ref (tree index, tree class_decl) +gfc_get_class_array_ref (tree index, tree class_decl, tree data_comp) { - tree data = gfc_class_data_get (class_decl); + tree data = data_comp != NULL_TREE ? data_comp : + gfc_class_data_get (class_decl); tree size = gfc_class_vtab_size_get (class_decl); tree offset = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type, @@ -1075,6 +1076,7 @@ gfc_copy_class_to_class (tree from, tree to, tree nelems, bool unlimited) tree stdcopy; tree extcopy; tree index; + bool is_from_desc = false, is_to_class = false; args = NULL; /* To prevent warnings on uninitialized variables. */ @@ -1088,7 +1090,19 @@ gfc_copy_class_to_class (tree from, tree to, tree nelems, bool unlimited) fcn_type = TREE_TYPE (TREE_TYPE (fcn)); if (from != NULL_TREE) - from_data = gfc_class_data_get (from); + { + is_from_desc = GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (from)); + if (is_from_desc) + { + from_data = from; + from = GFC_DECL_SAVED_DESCRIPTOR (from); + } + else + { + from_data = gfc_class_data_get (from); + is_from_desc = GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (from_data)); + } + } else from_data = gfc_class_vtab_def_init_get (to); @@ -1100,9 +1114,16 @@ gfc_copy_class_to_class (tree from, tree to, tree nelems, bool unlimited) from_len = integer_zero_node; } - to_data = gfc_class_data_get (to); - if (unlimited) - to_len = gfc_class_len_get (to); + if (GFC_CLASS_TYPE_P (TREE_TYPE (to))) + { + is_to_class = true; + to_data = gfc_class_data_get (to); + if (unlimited) + to_len = gfc_class_len_get (to); + } + else + /* When to is a BT_DERIVED and not a BT_CLASS, then to_data == to. */ + to_data = to; if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (to_data))) { @@ -1118,15 +1139,23 @@ gfc_copy_class_to_class (tree from, tree to, tree nelems, bool unlimited) nelems = gfc_evaluate_now (tmp, &body); index = gfc_create_var (gfc_array_index_type, "S"); - if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (from_data))) + if (is_from_desc) { - from_ref = gfc_get_class_array_ref (index, from); + from_ref = gfc_get_class_array_ref (index, from, from_data); vec_safe_push (args, from_ref); } else vec_safe_push (args, from_data); - to_ref = gfc_get_class_array_ref (index, to); + if (is_to_class) + to_ref = gfc_get_class_array_ref (index, to, to_data); + else + { + tmp = gfc_conv_array_data (to); + tmp = build_fold_indirect_ref_loc (input_location, tmp); + to_ref = gfc_build_addr_expr (NULL_TREE, + gfc_build_array_ref (tmp, index, to)); + } vec_safe_push (args, to_ref); tmp = build_call_vec (fcn_type, fcn, args); @@ -1183,7 +1212,7 @@ gfc_copy_class_to_class (tree from, tree to, tree nelems, bool unlimited) } else { - gcc_assert (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (from_data))); + gcc_assert (!is_from_desc); vec_safe_push (args, from_data); vec_safe_push (args, to_data); stdcopy = build_call_vec (fcn_type, fcn, args); |