re PR fortran/37336 ([F03] Finish derived-type finalization)
2012-11-03 Tobias Burnus <burnus@net-b.de> PR fortran/37336 * class.c (finalizer_insert_packed_call): New static function. (finalize_component, generate_finalization_wrapper): Fix coarray handling and packing. From-SVN: r194075
This commit is contained in:
parent
9cc263b852
commit
29a7d776ea
2 changed files with 450 additions and 105 deletions
|
@ -1,3 +1,10 @@
|
|||
2012-11-03 Tobias Burnus <burnus@net-b.de>
|
||||
|
||||
PR fortran/37336
|
||||
* class.c (finalizer_insert_packed_call): New static function.
|
||||
(finalize_component, generate_finalization_wrapper):
|
||||
Fix coarray handling and packing.
|
||||
|
||||
2012-12-02 Paul Thomas <pault@gcc.gnu.org>
|
||||
|
||||
* resolve.c (resolve_allocate_deallocate,
|
||||
|
@ -5,7 +12,7 @@
|
|||
193778, which were accidentally reverted by the previous patch.
|
||||
|
||||
2012-12-01 Alessandro Fanfarillo <alessandro.fanfarillo@gmail.com>
|
||||
Paul Thomas <pault@gcc.gnu.org>
|
||||
Paul Thomas <pault@gcc.gnu.org>
|
||||
|
||||
PR fortran/46897
|
||||
* gfortran.h : Add bit field 'defined_assign_comp' to
|
||||
|
|
|
@ -731,7 +731,7 @@ has_finalizer_component (gfc_symbol *derived)
|
|||
|
||||
static void
|
||||
finalize_component (gfc_expr *expr, gfc_symbol *derived, gfc_component *comp,
|
||||
gfc_expr *stat, gfc_code **code)
|
||||
gfc_symbol *stat, gfc_symbol *fini_coarray, gfc_code **code)
|
||||
{
|
||||
gfc_expr *e;
|
||||
gfc_ref *ref;
|
||||
|
@ -779,12 +779,36 @@ finalize_component (gfc_expr *expr, gfc_symbol *derived, gfc_component *comp,
|
|||
e->rank = ref->next->u.ar.as->rank;
|
||||
}
|
||||
|
||||
/* Call DEALLOCATE (comp, stat=ignore). */
|
||||
if (comp->attr.allocatable
|
||||
|| (comp->ts.type == BT_CLASS && CLASS_DATA (comp)
|
||||
&& CLASS_DATA (comp)->attr.allocatable))
|
||||
{
|
||||
/* Call DEALLOCATE (comp, stat=ignore). */
|
||||
gfc_code *dealloc;
|
||||
gfc_code *dealloc, *block = NULL;
|
||||
|
||||
/* Add IF (fini_coarray). */
|
||||
if (comp->attr.codimension
|
||||
|| (comp->ts.type == BT_CLASS && CLASS_DATA (comp)
|
||||
&& CLASS_DATA (comp)->attr.allocatable))
|
||||
{
|
||||
block = XCNEW (gfc_code);
|
||||
if (*code)
|
||||
{
|
||||
(*code)->next = block;
|
||||
(*code) = (*code)->next;
|
||||
}
|
||||
else
|
||||
(*code) = block;
|
||||
|
||||
block->loc = gfc_current_locus;
|
||||
block->op = EXEC_IF;
|
||||
|
||||
block->block = XCNEW (gfc_code);
|
||||
block = block->block;
|
||||
block->loc = gfc_current_locus;
|
||||
block->op = EXEC_IF;
|
||||
block->expr1 = gfc_lval_expr_from_sym (fini_coarray);
|
||||
}
|
||||
|
||||
dealloc = XCNEW (gfc_code);
|
||||
dealloc->op = EXEC_DEALLOCATE;
|
||||
|
@ -792,9 +816,11 @@ finalize_component (gfc_expr *expr, gfc_symbol *derived, gfc_component *comp,
|
|||
|
||||
dealloc->ext.alloc.list = gfc_get_alloc ();
|
||||
dealloc->ext.alloc.list->expr = e;
|
||||
dealloc->expr1 = gfc_lval_expr_from_sym (stat);
|
||||
|
||||
dealloc->expr1 = stat;
|
||||
if (*code)
|
||||
if (block)
|
||||
block->next = dealloc;
|
||||
else if (*code)
|
||||
{
|
||||
(*code)->next = dealloc;
|
||||
(*code) = (*code)->next;
|
||||
|
@ -839,7 +865,7 @@ finalize_component (gfc_expr *expr, gfc_symbol *derived, gfc_component *comp,
|
|||
gfc_component *c;
|
||||
|
||||
for (c = comp->ts.u.derived->components; c; c = c->next)
|
||||
finalize_component (e, c->ts.u.derived, c, stat, code);
|
||||
finalize_component (e, comp->ts.u.derived, c, stat, fini_coarray, code);
|
||||
gfc_free_expr (e);
|
||||
}
|
||||
}
|
||||
|
@ -847,12 +873,11 @@ finalize_component (gfc_expr *expr, gfc_symbol *derived, gfc_component *comp,
|
|||
|
||||
/* Generate code equivalent to
|
||||
CALL C_F_POINTER (TRANSFER (TRANSFER (C_LOC (array, cptr), c_intptr)
|
||||
+ idx * STORAGE_SIZE (array)/NUMERIC_STORAGE_SIZE., c_ptr),
|
||||
ptr). */
|
||||
+ idx * stride, c_ptr), ptr). */
|
||||
|
||||
static gfc_code *
|
||||
finalization_scalarizer (gfc_symbol *idx, gfc_symbol *array, gfc_symbol *ptr,
|
||||
gfc_namespace *sub_ns)
|
||||
gfc_expr *stride, gfc_namespace *sub_ns)
|
||||
{
|
||||
gfc_code *block;
|
||||
gfc_expr *expr, *expr2, *expr3;
|
||||
|
@ -919,40 +944,13 @@ finalization_scalarizer (gfc_symbol *idx, gfc_symbol *array, gfc_symbol *ptr,
|
|||
expr->ts.kind = gfc_index_integer_kind;
|
||||
expr2->value.function.actual->expr = expr;
|
||||
|
||||
/* STORAGE_SIZE (...) / NUMERIC_STORAGE_SIZE. */
|
||||
block->ext.actual->expr = gfc_get_expr ();
|
||||
expr = block->ext.actual->expr;
|
||||
expr->expr_type = EXPR_OP;
|
||||
expr->value.op.op = INTRINSIC_DIVIDE;
|
||||
|
||||
/* STORAGE_SIZE (array,kind=c_intptr_t). */
|
||||
expr->value.op.op1 = gfc_get_expr ();
|
||||
expr->value.op.op1->expr_type = EXPR_FUNCTION;
|
||||
expr->value.op.op1->value.function.isym
|
||||
= gfc_intrinsic_function_by_id (GFC_ISYM_STORAGE_SIZE);
|
||||
gfc_get_sym_tree ("storage_size", sub_ns, &expr->value.op.op1->symtree,
|
||||
false);
|
||||
expr->value.op.op1->symtree->n.sym->attr.flavor = FL_PROCEDURE;
|
||||
expr->value.op.op1->symtree->n.sym->attr.intrinsic = 1;
|
||||
gfc_commit_symbol (expr->value.op.op1->symtree->n.sym);
|
||||
expr->value.op.op1->value.function.actual = gfc_get_actual_arglist ();
|
||||
expr->value.op.op1->value.function.actual->expr
|
||||
= gfc_lval_expr_from_sym (array);
|
||||
expr->value.op.op1->value.function.actual->next = gfc_get_actual_arglist ();
|
||||
expr->value.op.op1->value.function.actual->next->expr
|
||||
= gfc_get_int_expr (gfc_index_integer_kind, NULL, 0);
|
||||
expr->value.op.op2 = gfc_get_int_expr (gfc_index_integer_kind, NULL,
|
||||
gfc_character_storage_size);
|
||||
expr->value.op.op1->ts = expr->value.op.op2->ts;
|
||||
expr->ts = expr->value.op.op1->ts;
|
||||
|
||||
/* Offset calculation: idx * (STORAGE_SIZE (...) / NUMERIC_STORAGE_SIZE). */
|
||||
/* Offset calculation: idx * stride (in bytes). */
|
||||
block->ext.actual->expr = gfc_get_expr ();
|
||||
expr3 = block->ext.actual->expr;
|
||||
expr3->expr_type = EXPR_OP;
|
||||
expr3->value.op.op = INTRINSIC_TIMES;
|
||||
expr3->value.op.op1 = gfc_lval_expr_from_sym (idx);
|
||||
expr3->value.op.op2 = expr;
|
||||
expr3->value.op.op2 = stride;
|
||||
expr3->ts = expr->ts;
|
||||
|
||||
/* <array addr> + <offset>. */
|
||||
|
@ -972,6 +970,265 @@ finalization_scalarizer (gfc_symbol *idx, gfc_symbol *array, gfc_symbol *ptr,
|
|||
}
|
||||
|
||||
|
||||
/* Insert code of the following form:
|
||||
|
||||
if (stride == STORAGE_SIZE (array)/NUMERIC_STORAGE_SIZE
|
||||
|| 0 == STORAGE_SIZE (array)) then
|
||||
call final_rank3 (array)
|
||||
else
|
||||
block
|
||||
type(t) :: tmp(shape (array))
|
||||
|
||||
do i = 0, size (array)-1
|
||||
addr = transfer (c_loc (array), addr) + i * stride
|
||||
call c_f_pointer (transfer (addr, cptr), ptr)
|
||||
|
||||
addr = transfer (c_loc (tmp), addr)
|
||||
+ i * STORAGE_SIZE (array)/NUMERIC_STORAGE_SIZE
|
||||
call c_f_pointer (transfer (addr, cptr), ptr2)
|
||||
ptr2 = ptr
|
||||
end do
|
||||
call final_rank3 (tmp)
|
||||
end block
|
||||
end if */
|
||||
|
||||
static void
|
||||
finalizer_insert_packed_call (gfc_code *block, gfc_finalizer *fini,
|
||||
gfc_symbol *array, gfc_symbol *stride,
|
||||
gfc_symbol *idx, gfc_symbol *ptr,
|
||||
gfc_symbol *nelem, gfc_symtree *size_intr,
|
||||
gfc_namespace *sub_ns)
|
||||
{
|
||||
gfc_symbol *tmp_array, *ptr2;
|
||||
gfc_expr *size_expr;
|
||||
gfc_namespace *ns;
|
||||
gfc_iterator *iter;
|
||||
int i;
|
||||
|
||||
block->next = XCNEW (gfc_code);
|
||||
block = block->next;
|
||||
block->loc = gfc_current_locus;
|
||||
block->op = EXEC_IF;
|
||||
|
||||
block->block = XCNEW (gfc_code);
|
||||
block = block->block;
|
||||
block->loc = gfc_current_locus;
|
||||
block->op = EXEC_IF;
|
||||
|
||||
/* size_expr = STORAGE_SIZE (...) / NUMERIC_STORAGE_SIZE. */
|
||||
size_expr = gfc_get_expr ();
|
||||
size_expr->where = gfc_current_locus;
|
||||
size_expr->expr_type = EXPR_OP;
|
||||
size_expr->value.op.op = INTRINSIC_DIVIDE;
|
||||
|
||||
/* STORAGE_SIZE (array,kind=c_intptr_t). */
|
||||
size_expr->value.op.op1 = gfc_get_expr ();
|
||||
size_expr->value.op.op1->where = gfc_current_locus;
|
||||
size_expr->value.op.op1->expr_type = EXPR_FUNCTION;
|
||||
size_expr->value.op.op1->value.function.isym
|
||||
= gfc_intrinsic_function_by_id (GFC_ISYM_STORAGE_SIZE);
|
||||
gfc_get_sym_tree ("storage_size", sub_ns, &size_expr->value.op.op1->symtree,
|
||||
false);
|
||||
size_expr->value.op.op1->symtree->n.sym->attr.flavor = FL_PROCEDURE;
|
||||
size_expr->value.op.op1->symtree->n.sym->attr.intrinsic = 1;
|
||||
gfc_commit_symbol (size_expr->value.op.op1->symtree->n.sym);
|
||||
size_expr->value.op.op1->value.function.actual = gfc_get_actual_arglist ();
|
||||
size_expr->value.op.op1->value.function.actual->expr
|
||||
= gfc_lval_expr_from_sym (array);
|
||||
size_expr->value.op.op1->value.function.actual->next = gfc_get_actual_arglist ();
|
||||
size_expr->value.op.op1->value.function.actual->next->expr
|
||||
= gfc_get_int_expr (gfc_index_integer_kind, NULL, 0);
|
||||
|
||||
/* NUMERIC_STORAGE_SIZE. */
|
||||
size_expr->value.op.op2 = gfc_get_int_expr (gfc_index_integer_kind, NULL,
|
||||
gfc_character_storage_size);
|
||||
size_expr->value.op.op1->ts = size_expr->value.op.op2->ts;
|
||||
size_expr->ts = size_expr->value.op.op1->ts;
|
||||
|
||||
/* IF condition: stride == size_expr || 0 == size_expr. */
|
||||
block->expr1 = gfc_get_expr ();
|
||||
block->expr1->expr_type = EXPR_FUNCTION;
|
||||
block->expr1->ts.type = BT_LOGICAL;
|
||||
block->expr1->ts.kind = 4;
|
||||
block->expr1->expr_type = EXPR_OP;
|
||||
block->expr1->where = gfc_current_locus;
|
||||
|
||||
block->expr1->value.op.op = INTRINSIC_OR;
|
||||
|
||||
/* stride == size_expr */
|
||||
block->expr1->value.op.op1 = gfc_get_expr ();
|
||||
block->expr1->value.op.op1->expr_type = EXPR_FUNCTION;
|
||||
block->expr1->value.op.op1->ts.type = BT_LOGICAL;
|
||||
block->expr1->value.op.op1->ts.kind = 4;
|
||||
block->expr1->value.op.op1->expr_type = EXPR_OP;
|
||||
block->expr1->value.op.op1->where = gfc_current_locus;
|
||||
block->expr1->value.op.op1->value.op.op = INTRINSIC_EQ;
|
||||
block->expr1->value.op.op1->value.op.op1 = gfc_lval_expr_from_sym (stride);
|
||||
block->expr1->value.op.op1->value.op.op2 = size_expr;
|
||||
|
||||
/* 0 == size_expr */
|
||||
block->expr1->value.op.op2 = gfc_get_expr ();
|
||||
block->expr1->value.op.op2->expr_type = EXPR_FUNCTION;
|
||||
block->expr1->value.op.op2->ts.type = BT_LOGICAL;
|
||||
block->expr1->value.op.op2->ts.kind = 4;
|
||||
block->expr1->value.op.op2->expr_type = EXPR_OP;
|
||||
block->expr1->value.op.op2->where = gfc_current_locus;
|
||||
block->expr1->value.op.op2->value.op.op = INTRINSIC_EQ;
|
||||
block->expr1->value.op.op2->value.op.op1 =
|
||||
gfc_get_int_expr (gfc_index_integer_kind, NULL, 0);
|
||||
block->expr1->value.op.op2->value.op.op2 = gfc_copy_expr (size_expr);
|
||||
|
||||
/* IF body: call final subroutine. */
|
||||
block->next = XCNEW (gfc_code);
|
||||
block->next->op = EXEC_CALL;
|
||||
block->next->loc = gfc_current_locus;
|
||||
block->next->symtree = fini->proc_tree;
|
||||
block->next->resolved_sym = fini->proc_tree->n.sym;
|
||||
block->next->ext.actual = gfc_get_actual_arglist ();
|
||||
block->next->ext.actual->expr = gfc_lval_expr_from_sym (array);
|
||||
|
||||
/* ELSE. */
|
||||
|
||||
block->block = XCNEW (gfc_code);
|
||||
block = block->block;
|
||||
block->loc = gfc_current_locus;
|
||||
block->op = EXEC_IF;
|
||||
|
||||
block->next = XCNEW (gfc_code);
|
||||
block = block->next;
|
||||
|
||||
/* BLOCK ... END BLOCK. */
|
||||
block->op = EXEC_BLOCK;
|
||||
block->loc = gfc_current_locus;
|
||||
ns = gfc_build_block_ns (sub_ns);
|
||||
block->ext.block.ns = ns;
|
||||
block->ext.block.assoc = NULL;
|
||||
|
||||
gfc_get_symbol ("ptr2", ns, &ptr2);
|
||||
ptr2->ts.type = BT_DERIVED;
|
||||
ptr2->ts.u.derived = array->ts.u.derived;
|
||||
ptr2->attr.flavor = FL_VARIABLE;
|
||||
ptr2->attr.pointer = 1;
|
||||
ptr2->attr.artificial = 1;
|
||||
gfc_set_sym_referenced (ptr2);
|
||||
gfc_commit_symbol (ptr2);
|
||||
|
||||
gfc_get_symbol ("tmp_array", ns, &tmp_array);
|
||||
tmp_array->ts.type = BT_DERIVED;
|
||||
tmp_array->ts.u.derived = array->ts.u.derived;
|
||||
tmp_array->attr.flavor = FL_VARIABLE;
|
||||
tmp_array->attr.contiguous = 1;
|
||||
tmp_array->attr.dimension = 1;
|
||||
tmp_array->attr.artificial = 1;
|
||||
tmp_array->as = gfc_get_array_spec();
|
||||
tmp_array->attr.intent = INTENT_INOUT;
|
||||
tmp_array->as->type = AS_EXPLICIT;
|
||||
tmp_array->as->rank = fini->proc_tree->n.sym->formal->sym->as->rank;
|
||||
|
||||
for (i = 0; i < tmp_array->as->rank; i++)
|
||||
{
|
||||
gfc_expr *shape_expr;
|
||||
tmp_array->as->lower[i] = gfc_get_int_expr (gfc_default_integer_kind,
|
||||
NULL, 1);
|
||||
/* SIZE (array, dim=i+1, kind=default_kind). */
|
||||
shape_expr = gfc_get_expr ();
|
||||
shape_expr->expr_type = EXPR_FUNCTION;
|
||||
shape_expr->value.function.isym
|
||||
= gfc_intrinsic_function_by_id (GFC_ISYM_SIZE);
|
||||
shape_expr->symtree = size_intr;
|
||||
shape_expr->value.function.actual = gfc_get_actual_arglist ();
|
||||
shape_expr->value.function.actual->expr = gfc_lval_expr_from_sym (array);
|
||||
shape_expr->value.function.actual->next = gfc_get_actual_arglist ();
|
||||
shape_expr->value.function.actual->next->expr
|
||||
= gfc_get_int_expr (gfc_default_integer_kind, NULL, i+1);
|
||||
shape_expr->value.function.actual->next->next = gfc_get_actual_arglist ();
|
||||
shape_expr->value.function.actual->next->next->expr
|
||||
= gfc_get_int_expr (gfc_default_integer_kind, NULL, 0);
|
||||
shape_expr->ts = shape_expr->value.function.isym->ts;
|
||||
|
||||
tmp_array->as->upper[i] = shape_expr;
|
||||
}
|
||||
gfc_set_sym_referenced (tmp_array);
|
||||
gfc_commit_symbol (tmp_array);
|
||||
|
||||
/* Create loop. */
|
||||
iter = gfc_get_iterator ();
|
||||
iter->var = gfc_lval_expr_from_sym (idx);
|
||||
iter->start = gfc_get_int_expr (gfc_index_integer_kind, NULL, 0);
|
||||
iter->end = gfc_lval_expr_from_sym (nelem);
|
||||
iter->step = gfc_get_int_expr (gfc_index_integer_kind, NULL, 1);
|
||||
|
||||
block = XCNEW (gfc_code);
|
||||
ns->code = block;
|
||||
block->op = EXEC_DO;
|
||||
block->loc = gfc_current_locus;
|
||||
block->ext.iterator = iter;
|
||||
block->block = gfc_get_code ();
|
||||
block->block->op = EXEC_DO;
|
||||
|
||||
/* Create code for
|
||||
CALL C_F_POINTER (TRANSFER (TRANSFER (C_LOC (array, cptr), c_intptr)
|
||||
+ idx * stride, c_ptr), ptr). */
|
||||
block->block->next = finalization_scalarizer (idx, array, ptr,
|
||||
gfc_lval_expr_from_sym (stride),
|
||||
sub_ns);
|
||||
block->block->next->next = finalization_scalarizer (idx, tmp_array, ptr2,
|
||||
gfc_copy_expr (size_expr),
|
||||
sub_ns);
|
||||
/* ptr2 = ptr. */
|
||||
block->block->next->next->next = XCNEW (gfc_code);
|
||||
block->block->next->next->next->op = EXEC_ASSIGN;
|
||||
block->block->next->next->next->loc = gfc_current_locus;
|
||||
block->block->next->next->next->expr1 = gfc_lval_expr_from_sym (ptr2);
|
||||
block->block->next->next->next->expr2 = gfc_lval_expr_from_sym (ptr);
|
||||
|
||||
block->next = XCNEW (gfc_code);
|
||||
block = block->next;
|
||||
block->op = EXEC_CALL;
|
||||
block->loc = gfc_current_locus;
|
||||
block->symtree = fini->proc_tree;
|
||||
block->resolved_sym = fini->proc_tree->n.sym;
|
||||
block->ext.actual = gfc_get_actual_arglist ();
|
||||
block->ext.actual->expr = gfc_lval_expr_from_sym (tmp_array);
|
||||
|
||||
if (fini->proc_tree->n.sym->formal->sym->attr.intent == INTENT_IN)
|
||||
return;
|
||||
|
||||
/* Copy back. */
|
||||
|
||||
/* Loop. */
|
||||
iter = gfc_get_iterator ();
|
||||
iter->var = gfc_lval_expr_from_sym (idx);
|
||||
iter->start = gfc_get_int_expr (gfc_index_integer_kind, NULL, 0);
|
||||
iter->end = gfc_lval_expr_from_sym (nelem);
|
||||
iter->step = gfc_get_int_expr (gfc_index_integer_kind, NULL, 1);
|
||||
|
||||
block->next = XCNEW (gfc_code);
|
||||
block = block->next;
|
||||
block->op = EXEC_DO;
|
||||
block->loc = gfc_current_locus;
|
||||
block->ext.iterator = iter;
|
||||
block->block = gfc_get_code ();
|
||||
block->block->op = EXEC_DO;
|
||||
|
||||
/* Create code for
|
||||
CALL C_F_POINTER (TRANSFER (TRANSFER (C_LOC (array, cptr), c_intptr)
|
||||
+ idx * stride, c_ptr), ptr). */
|
||||
block->block->next = finalization_scalarizer (idx, array, ptr,
|
||||
gfc_lval_expr_from_sym (stride),
|
||||
sub_ns);
|
||||
block->block->next->next = finalization_scalarizer (idx, tmp_array, ptr2,
|
||||
gfc_copy_expr (size_expr),
|
||||
sub_ns);
|
||||
/* ptr = ptr2. */
|
||||
block->block->next->next->next = XCNEW (gfc_code);
|
||||
block->block->next->next->next->op = EXEC_ASSIGN;
|
||||
block->block->next->next->next->loc = gfc_current_locus;
|
||||
block->block->next->next->next->expr1 = gfc_lval_expr_from_sym (ptr);
|
||||
block->block->next->next->next->expr2 = gfc_lval_expr_from_sym (ptr2);
|
||||
}
|
||||
|
||||
|
||||
/* Generate the finalization/polymorphic freeing wrapper subroutine for the
|
||||
derived type "derived". The function first calls the approriate FINAL
|
||||
subroutine, then it DEALLOCATEs (finalizes/frees) the allocatable
|
||||
|
@ -979,19 +1236,28 @@ finalization_scalarizer (gfc_symbol *idx, gfc_symbol *array, gfc_symbol *ptr,
|
|||
subroutine of the parent. The generated wrapper procedure takes as argument
|
||||
an assumed-rank array.
|
||||
If neither allocatable components nor FINAL subroutines exists, the vtab
|
||||
will contain a NULL pointer. */
|
||||
will contain a NULL pointer.
|
||||
The generated function has the form
|
||||
_final(assumed-rank array, stride, skip_corarray)
|
||||
where the array has to be contiguous (except of the lowest dimension). The
|
||||
stride (in bytes) is used to allow different sizes for ancestor types by
|
||||
skipping over the additionally added components in the scalarizer. If
|
||||
"fini_coarray" is false, coarray components are not finalized to allow for
|
||||
the correct semantic with intrinsic assignment. */
|
||||
|
||||
static void
|
||||
generate_finalization_wrapper (gfc_symbol *derived, gfc_namespace *ns,
|
||||
const char *tname, gfc_component *vtab_final)
|
||||
{
|
||||
gfc_symbol *final, *array, *nelem;
|
||||
gfc_symbol *final, *array, *nelem, *fini_coarray, *stride;
|
||||
gfc_symbol *ptr = NULL, *idx = NULL;
|
||||
gfc_symtree *size_intr;
|
||||
gfc_component *comp;
|
||||
gfc_namespace *sub_ns;
|
||||
gfc_code *last_code;
|
||||
char name[GFC_MAX_SYMBOL_LEN+1];
|
||||
bool finalizable_comp = false;
|
||||
bool expr_null_wrapper = false;
|
||||
gfc_expr *ancestor_wrapper = NULL;
|
||||
|
||||
/* Search for the ancestor's finalizers. */
|
||||
|
@ -1011,40 +1277,44 @@ generate_finalization_wrapper (gfc_symbol *derived, gfc_namespace *ns,
|
|||
}
|
||||
}
|
||||
|
||||
/* No wrapper of the ancestor and no own FINAL subroutines and
|
||||
allocatable components: Return a NULL() expression. */
|
||||
/* No wrapper of the ancestor and no own FINAL subroutines and allocatable
|
||||
components: Return a NULL() expression; we defer this a bit to have have
|
||||
an interface declaration. */
|
||||
if ((!ancestor_wrapper || ancestor_wrapper->expr_type == EXPR_NULL)
|
||||
&& !derived->attr.alloc_comp
|
||||
&& (!derived->f2k_derived || !derived->f2k_derived->finalizers)
|
||||
&& !has_finalizer_component (derived))
|
||||
{
|
||||
vtab_final->initializer = gfc_get_null_expr (NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check whether there are new allocatable components. */
|
||||
for (comp = derived->components; comp; comp = comp->next)
|
||||
{
|
||||
if (comp == derived->components && derived->attr.extension
|
||||
&& ancestor_wrapper && ancestor_wrapper->expr_type != EXPR_NULL)
|
||||
expr_null_wrapper = true;
|
||||
else
|
||||
/* Check whether there are new allocatable components. */
|
||||
for (comp = derived->components; comp; comp = comp->next)
|
||||
{
|
||||
if (comp == derived->components && derived->attr.extension
|
||||
&& ancestor_wrapper && ancestor_wrapper->expr_type != EXPR_NULL)
|
||||
continue;
|
||||
|
||||
if (comp->ts.type != BT_CLASS && !comp->attr.pointer
|
||||
&& (comp->attr.alloc_comp || comp->attr.allocatable
|
||||
|| (comp->ts.type == BT_DERIVED
|
||||
&& has_finalizer_component (comp->ts.u.derived))))
|
||||
finalizable_comp = true;
|
||||
else if (comp->ts.type == BT_CLASS && CLASS_DATA (comp)
|
||||
&& CLASS_DATA (comp)->attr.allocatable)
|
||||
finalizable_comp = true;
|
||||
}
|
||||
if (comp->ts.type != BT_CLASS && !comp->attr.pointer
|
||||
&& (comp->attr.allocatable
|
||||
|| (comp->ts.type == BT_DERIVED
|
||||
&& (comp->ts.u.derived->attr.alloc_comp
|
||||
|| has_finalizer_component (comp->ts.u.derived)
|
||||
|| (comp->ts.u.derived->f2k_derived
|
||||
&& comp->ts.u.derived->f2k_derived->finalizers)))))
|
||||
finalizable_comp = true;
|
||||
else if (comp->ts.type == BT_CLASS && CLASS_DATA (comp)
|
||||
&& CLASS_DATA (comp)->attr.allocatable)
|
||||
finalizable_comp = true;
|
||||
}
|
||||
|
||||
/* If there is no new finalizer and no new allocatable, return with
|
||||
an expr to the ancestor's one. */
|
||||
if ((!derived->f2k_derived || !derived->f2k_derived->finalizers)
|
||||
&& !finalizable_comp)
|
||||
if (!expr_null_wrapper && !finalizable_comp
|
||||
&& (!derived->f2k_derived || !derived->f2k_derived->finalizers))
|
||||
{
|
||||
gcc_assert (ancestor_wrapper && ancestor_wrapper->ref == NULL
|
||||
&& ancestor_wrapper->expr_type == EXPR_VARIABLE);
|
||||
vtab_final->initializer = gfc_copy_expr (ancestor_wrapper);
|
||||
vtab_final->ts.interface = vtab_final->initializer->symtree->n.sym;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1057,12 +1327,13 @@ generate_finalization_wrapper (gfc_symbol *derived, gfc_namespace *ns,
|
|||
3. Call the ancestor's finalizer. */
|
||||
|
||||
/* Declare the wrapper function; it takes an assumed-rank array
|
||||
as argument. */
|
||||
and a VALUE logical as arguments. */
|
||||
|
||||
/* Set up the namespace. */
|
||||
sub_ns = gfc_get_namespace (ns, 0);
|
||||
sub_ns->sibling = ns->contained;
|
||||
ns->contained = sub_ns;
|
||||
if (!expr_null_wrapper)
|
||||
ns->contained = sub_ns;
|
||||
sub_ns->resolved = 1;
|
||||
|
||||
/* Set up the procedure symbol. */
|
||||
|
@ -1070,13 +1341,17 @@ generate_finalization_wrapper (gfc_symbol *derived, gfc_namespace *ns,
|
|||
gfc_get_symbol (name, sub_ns, &final);
|
||||
sub_ns->proc_name = final;
|
||||
final->attr.flavor = FL_PROCEDURE;
|
||||
final->attr.subroutine = 1;
|
||||
final->attr.pure = 1;
|
||||
final->attr.function = 1;
|
||||
final->attr.pure = 0;
|
||||
final->result = final;
|
||||
final->ts.type = BT_INTEGER;
|
||||
final->ts.kind = 4;
|
||||
final->attr.artificial = 1;
|
||||
final->attr.if_source = IFSRC_DECL;
|
||||
final->attr.if_source = expr_null_wrapper ? IFSRC_IFBODY : IFSRC_DECL;
|
||||
if (ns->proc_name->attr.flavor == FL_MODULE)
|
||||
final->module = ns->proc_name->name;
|
||||
gfc_set_sym_referenced (final);
|
||||
gfc_commit_symbol (final);
|
||||
|
||||
/* Set up formal argument. */
|
||||
gfc_get_symbol ("array", sub_ns, &array);
|
||||
|
@ -1096,6 +1371,50 @@ generate_finalization_wrapper (gfc_symbol *derived, gfc_namespace *ns,
|
|||
final->formal->sym = array;
|
||||
gfc_commit_symbol (array);
|
||||
|
||||
/* Set up formal argument. */
|
||||
gfc_get_symbol ("stride", sub_ns, &stride);
|
||||
stride->ts.type = BT_INTEGER;
|
||||
stride->ts.kind = gfc_index_integer_kind;
|
||||
stride->attr.flavor = FL_VARIABLE;
|
||||
stride->attr.dummy = 1;
|
||||
stride->attr.value = 1;
|
||||
stride->attr.artificial = 1;
|
||||
gfc_set_sym_referenced (stride);
|
||||
final->formal->next = gfc_get_formal_arglist ();
|
||||
final->formal->next->sym = stride;
|
||||
gfc_commit_symbol (stride);
|
||||
|
||||
/* Set up formal argument. */
|
||||
gfc_get_symbol ("fini_coarray", sub_ns, &fini_coarray);
|
||||
fini_coarray->ts.type = BT_LOGICAL;
|
||||
fini_coarray->ts.kind = 4;
|
||||
fini_coarray->attr.flavor = FL_VARIABLE;
|
||||
fini_coarray->attr.dummy = 1;
|
||||
fini_coarray->attr.value = 1;
|
||||
fini_coarray->attr.artificial = 1;
|
||||
gfc_set_sym_referenced (fini_coarray);
|
||||
final->formal->next->next = gfc_get_formal_arglist ();
|
||||
final->formal->next->next->sym = fini_coarray;
|
||||
gfc_commit_symbol (fini_coarray);
|
||||
|
||||
/* Return with a NULL() expression but with an interface which has
|
||||
the formal arguments. */
|
||||
if (expr_null_wrapper)
|
||||
{
|
||||
vtab_final->initializer = gfc_get_null_expr (NULL);
|
||||
vtab_final->ts.interface = final;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Set return value to 0. */
|
||||
last_code = XCNEW (gfc_code);
|
||||
last_code->op = EXEC_ASSIGN;
|
||||
last_code->loc = gfc_current_locus;
|
||||
last_code->expr1 = gfc_lval_expr_from_sym (final);
|
||||
last_code->expr2 = gfc_get_int_expr (4, NULL, 0);
|
||||
sub_ns->code = last_code;
|
||||
|
||||
/* Obtain the size (number of elements) of "array" MINUS ONE,
|
||||
which is used in the scalarization. */
|
||||
gfc_get_symbol ("nelem", sub_ns, &nelem);
|
||||
|
@ -1107,7 +1426,8 @@ generate_finalization_wrapper (gfc_symbol *derived, gfc_namespace *ns,
|
|||
gfc_commit_symbol (nelem);
|
||||
|
||||
/* Generate: nelem = SIZE (array) - 1. */
|
||||
last_code = XCNEW (gfc_code);
|
||||
last_code->next = XCNEW (gfc_code);
|
||||
last_code = last_code->next;
|
||||
last_code->op = EXEC_ASSIGN;
|
||||
last_code->loc = gfc_current_locus;
|
||||
|
||||
|
@ -1126,6 +1446,7 @@ generate_finalization_wrapper (gfc_symbol *derived, gfc_namespace *ns,
|
|||
= gfc_intrinsic_function_by_id (GFC_ISYM_SIZE);
|
||||
gfc_get_sym_tree ("size", sub_ns, &last_code->expr2->value.op.op1->symtree,
|
||||
false);
|
||||
size_intr = last_code->expr2->value.op.op1->symtree;
|
||||
last_code->expr2->value.op.op1->symtree->n.sym->attr.flavor = FL_PROCEDURE;
|
||||
last_code->expr2->value.op.op1->symtree->n.sym->attr.intrinsic = 1;
|
||||
gfc_commit_symbol (last_code->expr2->value.op.op1->symtree->n.sym);
|
||||
|
@ -1154,10 +1475,11 @@ generate_finalization_wrapper (gfc_symbol *derived, gfc_namespace *ns,
|
|||
|
||||
select case (rank (array))
|
||||
case (3)
|
||||
! If needed, the array is packed
|
||||
call final_rank3 (array)
|
||||
case default:
|
||||
do i = 0, size (array)-1
|
||||
addr = transfer (c_loc (array), addr) + i * STORAGE_SIZE (array)
|
||||
addr = transfer (c_loc (array), addr) + i * stride
|
||||
call c_f_pointer (transfer (addr, cptr), ptr)
|
||||
call elemental_final (ptr)
|
||||
end do
|
||||
|
@ -1168,6 +1490,23 @@ generate_finalization_wrapper (gfc_symbol *derived, gfc_namespace *ns,
|
|||
gfc_finalizer *fini, *fini_elem = NULL;
|
||||
gfc_code *block = NULL;
|
||||
|
||||
gfc_get_symbol ("idx", sub_ns, &idx);
|
||||
idx->ts.type = BT_INTEGER;
|
||||
idx->ts.kind = gfc_index_integer_kind;
|
||||
idx->attr.flavor = FL_VARIABLE;
|
||||
idx->attr.artificial = 1;
|
||||
gfc_set_sym_referenced (idx);
|
||||
gfc_commit_symbol (idx);
|
||||
|
||||
gfc_get_symbol ("ptr", sub_ns, &ptr);
|
||||
ptr->ts.type = BT_DERIVED;
|
||||
ptr->ts.u.derived = derived;
|
||||
ptr->attr.flavor = FL_VARIABLE;
|
||||
ptr->attr.pointer = 1;
|
||||
ptr->attr.artificial = 1;
|
||||
gfc_set_sym_referenced (ptr);
|
||||
gfc_commit_symbol (ptr);
|
||||
|
||||
/* SELECT CASE (RANK (array)). */
|
||||
last_code->next = XCNEW (gfc_code);
|
||||
last_code = last_code->next;
|
||||
|
@ -1221,14 +1560,20 @@ generate_finalization_wrapper (gfc_symbol *derived, gfc_namespace *ns,
|
|||
block->ext.block.case_list->high
|
||||
= block->ext.block.case_list->low;
|
||||
|
||||
/* CALL fini_rank (array). */
|
||||
block->next = XCNEW (gfc_code);
|
||||
block->next->op = EXEC_CALL;
|
||||
block->next->loc = gfc_current_locus;
|
||||
block->next->symtree = fini->proc_tree;
|
||||
block->next->resolved_sym = fini->proc_tree->n.sym;
|
||||
block->next->ext.actual = gfc_get_actual_arglist ();
|
||||
block->next->ext.actual->expr = gfc_lval_expr_from_sym (array);
|
||||
/* CALL fini_rank (array) - possibly with packing. */
|
||||
if (fini->proc_tree->n.sym->formal->sym->attr.dimension)
|
||||
finalizer_insert_packed_call (block, fini, array, stride, idx, ptr,
|
||||
nelem, size_intr, sub_ns);
|
||||
else
|
||||
{
|
||||
block->next = XCNEW (gfc_code);
|
||||
block->next->op = EXEC_CALL;
|
||||
block->next->loc = gfc_current_locus;
|
||||
block->next->symtree = fini->proc_tree;
|
||||
block->next->resolved_sym = fini->proc_tree->n.sym;
|
||||
block->next->ext.actual = gfc_get_actual_arglist ();
|
||||
block->next->ext.actual->expr = gfc_lval_expr_from_sym (array);
|
||||
}
|
||||
}
|
||||
|
||||
/* Elemental call - scalarized. */
|
||||
|
@ -1251,23 +1596,6 @@ generate_finalization_wrapper (gfc_symbol *derived, gfc_namespace *ns,
|
|||
block->op = EXEC_SELECT;
|
||||
block->ext.block.case_list = gfc_get_case ();
|
||||
|
||||
gfc_get_symbol ("idx", sub_ns, &idx);
|
||||
idx->ts.type = BT_INTEGER;
|
||||
idx->ts.kind = gfc_index_integer_kind;
|
||||
idx->attr.flavor = FL_VARIABLE;
|
||||
idx->attr.artificial = 1;
|
||||
gfc_set_sym_referenced (idx);
|
||||
gfc_commit_symbol (idx);
|
||||
|
||||
gfc_get_symbol ("ptr", sub_ns, &ptr);
|
||||
ptr->ts.type = BT_DERIVED;
|
||||
ptr->ts.u.derived = derived;
|
||||
ptr->attr.flavor = FL_VARIABLE;
|
||||
ptr->attr.pointer = 1;
|
||||
ptr->attr.artificial = 1;
|
||||
gfc_set_sym_referenced (ptr);
|
||||
gfc_commit_symbol (ptr);
|
||||
|
||||
/* Create loop. */
|
||||
iter = gfc_get_iterator ();
|
||||
iter->var = gfc_lval_expr_from_sym (idx);
|
||||
|
@ -1284,8 +1612,11 @@ generate_finalization_wrapper (gfc_symbol *derived, gfc_namespace *ns,
|
|||
|
||||
/* Create code for
|
||||
CALL C_F_POINTER (TRANSFER (TRANSFER (C_LOC (array, cptr), c_intptr)
|
||||
+ idx * STORAGE_SIZE (array), c_ptr), ptr). */
|
||||
block->block->next = finalization_scalarizer (idx, array, ptr, sub_ns);
|
||||
+ idx * stride, c_ptr), ptr). */
|
||||
block->block->next
|
||||
= finalization_scalarizer (idx, array, ptr,
|
||||
gfc_lval_expr_from_sym (stride),
|
||||
sub_ns);
|
||||
block = block->block->next;
|
||||
|
||||
/* CALL final_elemental (array). */
|
||||
|
@ -1356,8 +1687,11 @@ generate_finalization_wrapper (gfc_symbol *derived, gfc_namespace *ns,
|
|||
|
||||
/* Create code for
|
||||
CALL C_F_POINTER (TRANSFER (TRANSFER (C_LOC (array, cptr), c_intptr)
|
||||
+ idx * STORAGE_SIZE (array), c_ptr), ptr). */
|
||||
last_code->block->next = finalization_scalarizer (idx, array, ptr, sub_ns);
|
||||
+ idx * stride, c_ptr), ptr). */
|
||||
last_code->block->next
|
||||
= finalization_scalarizer (idx, array, ptr,
|
||||
gfc_lval_expr_from_sym (stride),
|
||||
sub_ns);
|
||||
block = last_code->block->next;
|
||||
|
||||
for (comp = derived->components; comp; comp = comp->next)
|
||||
|
@ -1367,7 +1701,7 @@ generate_finalization_wrapper (gfc_symbol *derived, gfc_namespace *ns,
|
|||
continue;
|
||||
|
||||
finalize_component (gfc_lval_expr_from_sym (ptr), derived, comp,
|
||||
gfc_lval_expr_from_sym (stat), &block);
|
||||
stat, fini_coarray, &block);
|
||||
if (!last_code->block->next)
|
||||
last_code->block->next = block;
|
||||
}
|
||||
|
@ -1386,9 +1720,13 @@ generate_finalization_wrapper (gfc_symbol *derived, gfc_namespace *ns,
|
|||
|
||||
last_code->ext.actual = gfc_get_actual_arglist ();
|
||||
last_code->ext.actual->expr = gfc_lval_expr_from_sym (array);
|
||||
last_code->ext.actual->next = gfc_get_actual_arglist ();
|
||||
last_code->ext.actual->next->expr = gfc_lval_expr_from_sym (stride);
|
||||
last_code->ext.actual->next->next = gfc_get_actual_arglist ();
|
||||
last_code->ext.actual->next->next->expr
|
||||
= gfc_lval_expr_from_sym (fini_coarray);
|
||||
}
|
||||
|
||||
gfc_commit_symbol (final);
|
||||
vtab_final->initializer = gfc_lval_expr_from_sym (final);
|
||||
vtab_final->ts.interface = final;
|
||||
}
|
||||
|
@ -1419,7 +1757,7 @@ add_procs_to_declared_vtab (gfc_symbol *derived, gfc_symbol *vtype)
|
|||
}
|
||||
|
||||
|
||||
/* Find (or generate) the symbol for a derived type's vtab. */
|
||||
/* Find or generate the symbol for a derived type's vtab. */
|
||||
|
||||
gfc_symbol *
|
||||
gfc_find_derived_vtab (gfc_symbol *derived)
|
||||
|
@ -1440,7 +1778,7 @@ gfc_find_derived_vtab (gfc_symbol *derived)
|
|||
if (ns)
|
||||
{
|
||||
char name[GFC_MAX_SYMBOL_LEN+1], tname[GFC_MAX_SYMBOL_LEN+1];
|
||||
|
||||
|
||||
get_unique_hashed_string (tname, derived);
|
||||
sprintf (name, "__vtab_%s", tname);
|
||||
|
||||
|
@ -1464,7 +1802,7 @@ gfc_find_derived_vtab (gfc_symbol *derived)
|
|||
vtab->attr.access = ACCESS_PUBLIC;
|
||||
gfc_set_sym_referenced (vtab);
|
||||
sprintf (name, "__vtype_%s", tname);
|
||||
|
||||
|
||||
gfc_find_symbol (name, ns, 0, &vtype);
|
||||
if (vtype == NULL)
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue