===================================================================
*************** gfc_trans_create_temp_array (stmtblock_t
tree nelem;
tree cond;
tree or_expr;
+ tree class_expr = NULL_TREE;
int n, dim, tmp_dim;
int total_dim = 0;
+ /* This signals a class array for which we need the size of the
+ dynamic type. Generate an eltype and then the class expression. */
+ if (eltype == NULL_TREE && initial)
+ {
+ if (POINTER_TYPE_P (TREE_TYPE (initial)))
+ class_expr = build_fold_indirect_ref_loc (input_location, initial);
+ eltype = TREE_TYPE (class_expr);
+ eltype = gfc_get_element_type (eltype);
+ /* Obtain the structure (class) expression. */
+ class_expr = TREE_OPERAND (class_expr, 0);
+ gcc_assert (class_expr);
+ }
+
memset (from, 0, sizeof (from));
memset (to, 0, sizeof (to));
*************** gfc_trans_create_temp_array (stmtblock_t
/* Get the size of the array. */
if (size && !callee_alloc)
{
/* If or_expr is true, then the extent in at least one
dimension is zero and the size is set to zero. */
size = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
or_expr, gfc_index_zero_node, size);
nelem = size;
size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
! size,
! fold_convert (gfc_array_index_type,
! TYPE_SIZE_UNIT (gfc_get_element_type (type))));
}
else
{
/* Get the size of the array. */
if (size && !callee_alloc)
{
+ tree elemsize;
/* If or_expr is true, then the extent in at least one
dimension is zero and the size is set to zero. */
size = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
or_expr, gfc_index_zero_node, size);
nelem = size;
+ if (class_expr == NULL_TREE)
+ elemsize = fold_convert (gfc_array_index_type,
+ TYPE_SIZE_UNIT (gfc_get_element_type (type)));
+ else
+ elemsize = gfc_vtable_size_get (class_expr);
+
size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
! size, elemsize);
}
else
{
===================================================================
*************** gfc_conv_elemental_dependencies (gfc_se
|| (fsym->ts.type ==BT_DERIVED
&& fsym->attr.intent == INTENT_OUT))
initial = parmse.expr;
else
initial = NULL_TREE;
! /* Find the type of the temporary to create; we don't use the type
! of e itself as this breaks for subcomponent-references in e (where
! the type of e is that of the final reference, but parmse.expr's
! type corresponds to the full derived-type). */
! /* TODO: Fix this somehow so we don't need a temporary of the whole
! array but instead only the components referenced. */
! temptype = TREE_TYPE (parmse.expr); /* Pointer to descriptor. */
! gcc_assert (TREE_CODE (temptype) == POINTER_TYPE);
! temptype = TREE_TYPE (temptype);
! temptype = gfc_get_element_type (temptype);
/* Generate the temporary. Cleaning up the temporary should be the
very last thing done, so we add the code to a new block and add it
|| (fsym->ts.type ==BT_DERIVED
&& fsym->attr.intent == INTENT_OUT))
initial = parmse.expr;
+ /* For class expressions, we always initialize with the copy of
+ the values. */
+ else if (e->ts.type == BT_CLASS)
+ initial = parmse.expr;
else
initial = NULL_TREE;
! if (e->ts.type != BT_CLASS)
! {
! /* Find the type of the temporary to create; we don't use the type
! of e itself as this breaks for subcomponent-references in e
! (where the type of e is that of the final reference, but
! parmse.expr's type corresponds to the full derived-type). */
! /* TODO: Fix this somehow so we don't need a temporary of the whole
! array but instead only the components referenced. */
! temptype = TREE_TYPE (parmse.expr); /* Pointer to descriptor. */
! gcc_assert (TREE_CODE (temptype) == POINTER_TYPE);
! temptype = TREE_TYPE (temptype);
! temptype = gfc_get_element_type (temptype);
! }
!
! else
! /* For class arrays signal that the size of the dynamic type has to
! be obtained from the vtable, using the 'initial' expression. */
! temptype = NULL_TREE;
/* Generate the temporary. Cleaning up the temporary should be the
very last thing done, so we add the code to a new block and add it
*************** gfc_conv_elemental_dependencies (gfc_se
/* Update other ss' delta. */
gfc_set_delta (loopse->loop);
! /* Copy the result back using unpack. */
! tmp = build_call_expr_loc (input_location,
! gfor_fndecl_in_unpack, 2, parmse.expr, data);
gfc_add_expr_to_block (&se->post, tmp);
/* parmse.pre is already added above. */
/* Update other ss' delta. */
gfc_set_delta (loopse->loop);
! /* Copy the result back using unpack..... */
! if (e->ts.type != BT_CLASS)
! tmp = build_call_expr_loc (input_location,
! gfor_fndecl_in_unpack, 2, parmse.expr, data);
! else
! {
! /* ... except for class results where the copy is
! unconditional. */
! tmp = build_fold_indirect_ref_loc (input_location, parmse.expr);
! tmp = gfc_conv_descriptor_data_get (tmp);
! tmp = build_call_expr_loc (input_location,
! builtin_decl_explicit (BUILT_IN_MEMCPY),
! 3, tmp, data, size);
! }
gfc_add_expr_to_block (&se->post, tmp);
/* parmse.pre is already added above. */
===================================================================
*************** contains
allocate (tmp(size (a, 1)), source = a)
index_array = [(i, i = 1, size (a, 1))]
call internal_qsort (tmp, index_array) ! Do not move class elements around until end
! do i = 1, size (a, 1) ! Since they can be of arbitrary size.
! a(i) = tmp(index_array(i)) ! Vector index array would be neater
! end do
! ! a = tmp(index_array) ! Like this - TODO: fixme
end subroutine qsort
recursive subroutine internal_qsort (x, iarray)
allocate (tmp(size (a, 1)), source = a)
index_array = [(i, i = 1, size (a, 1))]
call internal_qsort (tmp, index_array) ! Do not move class elements around until end
! a = tmp(index_array)
end subroutine qsort
recursive subroutine internal_qsort (x, iarray)