aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran
diff options
context:
space:
mode:
authorPaul Thomas <pault@gcc.gnu.org>2015-10-25 21:31:12 +0000
committerPaul Thomas <pault@gcc.gnu.org>2015-10-25 21:31:12 +0000
commit6a4236ceb1020bcb8af45f2497672435d75c2c84 (patch)
treedad621aa8de0b50bc5d3198c9849d312a7e7ddca /gcc/fortran
parent9621d52481aef48baf90fb0008b4e2ff403bc90b (diff)
downloadgcc-6a4236ceb1020bcb8af45f2497672435d75c2c84.zip
gcc-6a4236ceb1020bcb8af45f2497672435d75c2c84.tar.gz
gcc-6a4236ceb1020bcb8af45f2497672435d75c2c84.tar.bz2
re PR fortran/67171 (sourced allocation)
2015-01-25 Paul Thomas <pault@gcc.gnu.org> PR fortran/67171 * trans-array.c (structure_alloc_comps): On deallocation of class components, reset the vptr to the declared type vtable and reset the _len field of unlimited polymorphic components. *trans-expr.c (gfc_find_and_cut_at_last_class_ref): Bail out on allocatable component references to the right of part reference with non-zero rank and return NULL. (gfc_reset_vptr): Simplify this function by using the function gfc_get_vptr_from_expr. Return if the vptr is NULL_TREE. (gfc_reset_len): If gfc_find_and_cut_at_last_class_ref returns NULL return. * trans-stmt.c (gfc_trans_allocate): Rely on the use of gfc_trans_assignment if expr3 is a variable expression since this deals correctly with array sections. 2015-01-25 Paul Thomas <pault@gcc.gnu.org> PR fortran/67171 * gfortran.dg/allocate_with_source_12.f03: New test PR fortran/61819 * gfortran.dg/allocate_with_source_13.f03: New test PR fortran/61830 * gfortran.dg/allocate_with_source_14.f03: New test From-SVN: r229303
Diffstat (limited to 'gcc/fortran')
-rw-r--r--gcc/fortran/ChangeLog21
-rw-r--r--gcc/fortran/trans-array.c32
-rw-r--r--gcc/fortran/trans-expr.c70
-rw-r--r--gcc/fortran/trans-stmt.c9
4 files changed, 96 insertions, 36 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 1a351be..668013d 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,8 +1,25 @@
+2015-01-25 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/67171
+ * trans-array.c (structure_alloc_comps): On deallocation of
+ class components, reset the vptr to the declared type vtable
+ and reset the _len field of unlimited polymorphic components.
+ *trans-expr.c (gfc_find_and_cut_at_last_class_ref): Bail out on
+ allocatable component references to the right of part reference
+ with non-zero rank and return NULL.
+ (gfc_reset_vptr): Simplify this function by using the function
+ gfc_get_vptr_from_expr. Return if the vptr is NULL_TREE.
+ (gfc_reset_len): If gfc_find_and_cut_at_last_class_ref returns
+ NULL return.
+ * trans-stmt.c (gfc_trans_allocate): Rely on the use of
+ gfc_trans_assignment if expr3 is a variable expression since
+ this deals correctly with array sections.
+
2015-10-25 Andre Vehreschild <vehre@gcc.gnu.org>
PR fortran/66927
- PR fortran/67044
- * trans-array.c (build_array_ref): Modified call to
+ 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
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index 45c18a5..b726998 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -8024,6 +8024,38 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
build_int_cst (TREE_TYPE (comp), 0));
}
gfc_add_expr_to_block (&tmpblock, tmp);
+
+ /* Finally, reset the vptr to the declared type vtable and, if
+ necessary reset the _len field.
+
+ First recover the reference to the component and obtain
+ the vptr. */
+ comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
+ decl, cdecl, NULL_TREE);
+ tmp = gfc_class_vptr_get (comp);
+
+ if (UNLIMITED_POLY (c))
+ {
+ /* Both vptr and _len field should be nulled. */
+ gfc_add_modify (&tmpblock, tmp,
+ build_int_cst (TREE_TYPE (tmp), 0));
+ tmp = gfc_class_len_get (comp);
+ gfc_add_modify (&tmpblock, tmp,
+ build_int_cst (TREE_TYPE (tmp), 0));
+ }
+ else
+ {
+ /* Build the vtable address and set the vptr with it. */
+ tree vtab;
+ gfc_symbol *vtable;
+ vtable = gfc_find_derived_vtab (c->ts.u.derived);
+ vtab = vtable->backend_decl;
+ if (vtab == NULL_TREE)
+ vtab = gfc_get_symbol_decl (vtable);
+ vtab = gfc_build_addr_expr (NULL, vtab);
+ vtab = fold_convert (TREE_TYPE (tmp), vtab);
+ gfc_add_modify (&tmpblock, tmp, vtab);
+ }
}
if (cmp_has_alloc_comps
diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index 9585de6..f8ed0df 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -271,15 +271,29 @@ gfc_expr *
gfc_find_and_cut_at_last_class_ref (gfc_expr *e)
{
gfc_expr *base_expr;
- gfc_ref *ref, *class_ref, *tail;
+ gfc_ref *ref, *class_ref, *tail, *array_ref;
/* Find the last class reference. */
class_ref = NULL;
+ array_ref = NULL;
for (ref = e->ref; ref; ref = ref->next)
{
+ if (ref->type == REF_ARRAY
+ && ref->u.ar.type != AR_ELEMENT)
+ array_ref = ref;
+
if (ref->type == REF_COMPONENT
&& ref->u.c.component->ts.type == BT_CLASS)
+ {
+ /* Component to the right of a part reference with nonzero rank
+ must not have the ALLOCATABLE attribute. If attempts are
+ made to reference such a component reference, an error results
+ followed by anICE. */
+ if (array_ref
+ && CLASS_DATA (ref->u.c.component)->attr.allocatable)
+ return NULL;
class_ref = ref;
+ }
if (ref->next == NULL)
break;
@@ -320,47 +334,37 @@ gfc_find_and_cut_at_last_class_ref (gfc_expr *e)
void
gfc_reset_vptr (stmtblock_t *block, gfc_expr *e)
{
- gfc_expr *rhs, *lhs = gfc_copy_expr (e);
gfc_symbol *vtab;
- tree tmp;
- gfc_ref *ref;
+ tree vptr;
+ tree vtable;
+ gfc_se se;
- /* If we have a class array, we need go back to the class
- container. */
- if (lhs->ref && lhs->ref->next && !lhs->ref->next->next
- && lhs->ref->next->type == REF_ARRAY
- && lhs->ref->next->u.ar.type == AR_FULL
- && lhs->ref->type == REF_COMPONENT
- && strcmp (lhs->ref->u.c.component->name, "_data") == 0)
- {
- gfc_free_ref_list (lhs->ref);
- lhs->ref = NULL;
- }
+ /* Evaluate the expression and obtain the vptr from it. */
+ gfc_init_se (&se, NULL);
+ if (e->rank)
+ gfc_conv_expr_descriptor (&se, e);
else
- for (ref = lhs->ref; ref; ref = ref->next)
- if (ref->next && ref->next->next && !ref->next->next->next
- && ref->next->next->type == REF_ARRAY
- && ref->next->next->u.ar.type == AR_FULL
- && ref->next->type == REF_COMPONENT
- && strcmp (ref->next->u.c.component->name, "_data") == 0)
- {
- gfc_free_ref_list (ref->next);
- ref->next = NULL;
- }
+ gfc_conv_expr (&se, e);
+ gfc_add_block_to_block (block, &se.pre);
+ vptr = gfc_get_vptr_from_expr (se.expr);
- gfc_add_vptr_component (lhs);
+ /* If a vptr is not found, we can do nothing more. */
+ if (vptr == NULL_TREE)
+ return;
if (UNLIMITED_POLY (e))
- rhs = gfc_get_null_expr (NULL);
+ gfc_add_modify (block, vptr, build_int_cst (TREE_TYPE (vptr), 0));
else
{
+ /* Return the vptr to the address of the declared type. */
vtab = gfc_find_derived_vtab (e->ts.u.derived);
- rhs = gfc_lval_expr_from_sym (vtab);
+ vtable = vtab->backend_decl;
+ if (vtable == NULL_TREE)
+ vtable = gfc_get_symbol_decl (vtab);
+ vtable = gfc_build_addr_expr (NULL, vtable);
+ vtable = fold_convert (TREE_TYPE (vptr), vtable);
+ gfc_add_modify (block, vptr, vtable);
}
- tmp = gfc_trans_pointer_assignment (lhs, rhs);
- gfc_add_expr_to_block (block, tmp);
- gfc_free_expr (lhs);
- gfc_free_expr (rhs);
}
@@ -372,6 +376,8 @@ gfc_reset_len (stmtblock_t *block, gfc_expr *expr)
gfc_expr *e;
gfc_se se_len;
e = gfc_find_and_cut_at_last_class_ref (expr);
+ if (e == NULL)
+ return;
gfc_add_len_component (e);
gfc_init_se (&se_len, NULL);
gfc_conv_expr (&se_len, e);
diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c
index 1bd131e..85558f0 100644
--- a/gcc/fortran/trans-stmt.c
+++ b/gcc/fortran/trans-stmt.c
@@ -5379,8 +5379,13 @@ gfc_trans_allocate (gfc_code * code)
will benefit of every enhancements gfc_trans_assignment ()
gets.
No need to check whether e3_is is E3_UNSET, because that is
- done by expr3 != NULL_TREE. */
- if (e3_is != E3_MOLD && expr3 != NULL_TREE
+ done by expr3 != NULL_TREE.
+ Exclude variables since the following block does not handle
+ array sections. In any case, there is no harm in sending
+ variables to gfc_trans_assignment because there is no
+ evaluation of variables. */
+ if (code->expr3->expr_type != EXPR_VARIABLE
+ && e3_is != E3_MOLD && expr3 != NULL_TREE
&& DECL_P (expr3) && DECL_ARTIFICIAL (expr3))
{
/* Build a temporary symtree and symbol. Do not add it to