PF fortran/60322
gcc/testsuite/ChangeLog: 2015-04-23 Andre Vehreschild <vehre@gmx.de> PF fortran/60322 * gfortran.dg/class_allocate_19.f03: New test. * gfortran.dg/class_array_20.f03: New test. * gfortran.dg/class_array_21.f03: New test. * gfortran.dg/finalize_10.f90: Corrected scan-trees. * gfortran.dg/finalize_15.f90: Fixing comparision to model initialization correctly. * gfortran.dg/finalize_29.f08: New test. gcc/fortran/ChangeLog: 2015-04-23 Andre Vehreschild <vehre@gmx.de> PR fortran/60322 * expr.c (gfc_lval_expr_from_sym): Code to select the regular or class array added. * gfortran.h: Add IS_CLASS_ARRAY macro. * trans-array.c (gfc_add_loop_ss_code): Treat class objects to be referenced always. (build_class_array_ref): Adapt retrieval of array descriptor. (build_array_ref): Likewise. (gfc_conv_array_ref): Hand the vptr or the descriptor to build_array_ref depending whether the sym is class or not. (gfc_trans_array_cobounds): Select correct gfc_array_spec for regular and class arrays. (gfc_trans_array_bounds): Likewise. (gfc_trans_dummy_array_bias): Likewise. (gfc_get_dataptr_offset): Correcting call of build_array_ref. (gfc_conv_expr_descriptor): Set the array's offset to -1 when lbound in inner most dim is 1 and symbol non-pointer/assoc. * trans-decl.c (gfc_build_qualified_array): Select correct gfc_array_spec for regular and class arrays. (gfc_build_dummy_array_decl): Likewise. (gfc_get_symbol_decl): Get a dummy array for class arrays. (gfc_trans_deferred_vars): Tell conv_expr that the descriptor is desired. * trans-expr.c (gfc_class_vptr_get): Get the class descriptor from the correct location for class arrays. (gfc_class_len_get): Likewise. (gfc_conv_intrinsic_to_class): Add handling of _len component. (gfc_conv_class_to_class): Prevent access to unset array data when the array is an optional argument. Add handling of _len component. (gfc_copy_class_to_class): Check that _def_init is non-NULL when used in _vptr->copy() (gfc_trans_class_init_assign): Ensure that the rank of _def_init is zero. (gfc_conv_component_ref): Get the _vptr along with _data refs. (gfc_conv_variable): Make sure the temp array descriptor is returned for class arrays, too, and that class arrays are dereferenced correctly. (gfc_conv_procedure_call): For polymorphic type initialization the initializer has to be a pointer to _def_init stored in a dummy variable, which then needs to be used by value. * trans-intrinsic.c (gfc_conv_intrinsic_sizeof): Use the temporary array descriptor for class arrays, too. (gfc_conv_intrinsic_storage_size): Likewise. (gfc_conv_intrinsic_loc): Add ref to _data for BT_CLASS expressions. * trans-stmt.c (trans_associate_var): Use a temporary array for the associate variable of class arrays, too, making the array one-based (lbound == 1). * trans-types.c (gfc_is_nodesc_array): Use the correct array data. * trans.c (gfc_build_array_ref): Use the dummy array descriptor when present. * trans.h: Add class_vptr to gfc_se for storing a class ref's vptr. From-SVN: r222361
This commit is contained in:
parent
eff973a26b
commit
f3b0bb7a56
@ -1,3 +1,61 @@
|
||||
2015-04-23 Andre Vehreschild <vehre@gmx.de>
|
||||
|
||||
PR fortran/60322
|
||||
* expr.c (gfc_lval_expr_from_sym): Code to select the regular
|
||||
or class array added.
|
||||
* gfortran.h: Add IS_CLASS_ARRAY macro.
|
||||
* trans-array.c (gfc_add_loop_ss_code): Treat class objects
|
||||
to be referenced always.
|
||||
(build_class_array_ref): Adapt retrieval of array descriptor.
|
||||
(build_array_ref): Likewise.
|
||||
(gfc_conv_array_ref): Hand the vptr or the descriptor to
|
||||
build_array_ref depending whether the sym is class or not.
|
||||
(gfc_trans_array_cobounds): Select correct gfc_array_spec for
|
||||
regular and class arrays.
|
||||
(gfc_trans_array_bounds): Likewise.
|
||||
(gfc_trans_dummy_array_bias): Likewise.
|
||||
(gfc_get_dataptr_offset): Correcting call of build_array_ref.
|
||||
(gfc_conv_expr_descriptor): Set the array's offset to -1 when
|
||||
lbound in inner most dim is 1 and symbol non-pointer/assoc.
|
||||
* trans-decl.c (gfc_build_qualified_array): Select correct
|
||||
gfc_array_spec for regular and class arrays.
|
||||
(gfc_build_dummy_array_decl): Likewise.
|
||||
(gfc_get_symbol_decl): Get a dummy array for class arrays.
|
||||
(gfc_trans_deferred_vars): Tell conv_expr that the descriptor
|
||||
is desired.
|
||||
* trans-expr.c (gfc_class_vptr_get): Get the class descriptor
|
||||
from the correct location for class arrays.
|
||||
(gfc_class_len_get): Likewise.
|
||||
(gfc_conv_intrinsic_to_class): Add handling of _len component.
|
||||
(gfc_conv_class_to_class): Prevent access to unset array data
|
||||
when the array is an optional argument. Add handling of _len
|
||||
component.
|
||||
(gfc_copy_class_to_class): Check that _def_init is non-NULL
|
||||
when used in _vptr->copy()
|
||||
(gfc_trans_class_init_assign): Ensure that the rank of
|
||||
_def_init is zero.
|
||||
(gfc_conv_component_ref): Get the _vptr along with _data refs.
|
||||
(gfc_conv_variable): Make sure the temp array descriptor is
|
||||
returned for class arrays, too, and that class arrays are
|
||||
dereferenced correctly.
|
||||
(gfc_conv_procedure_call): For polymorphic type initialization
|
||||
the initializer has to be a pointer to _def_init stored in a
|
||||
dummy variable, which then needs to be used by value.
|
||||
* trans-intrinsic.c (gfc_conv_intrinsic_sizeof): Use the
|
||||
temporary array descriptor for class arrays, too.
|
||||
(gfc_conv_intrinsic_storage_size): Likewise.
|
||||
(gfc_conv_intrinsic_loc): Add ref to _data for BT_CLASS
|
||||
expressions.
|
||||
* trans-stmt.c (trans_associate_var): Use a temporary array for
|
||||
the associate variable of class arrays, too, making the array
|
||||
one-based (lbound == 1).
|
||||
* trans-types.c (gfc_is_nodesc_array): Use the correct
|
||||
array data.
|
||||
* trans.c (gfc_build_array_ref): Use the dummy array descriptor
|
||||
when present.
|
||||
* trans.h: Add class_vptr to gfc_se for storing a class ref's
|
||||
vptr.
|
||||
|
||||
2015-04-22 Steven G. Kargl <kargl@gcc.gnu.org>
|
||||
|
||||
PR fortran/65429
|
||||
|
@ -4052,6 +4052,7 @@ gfc_expr *
|
||||
gfc_lval_expr_from_sym (gfc_symbol *sym)
|
||||
{
|
||||
gfc_expr *lval;
|
||||
gfc_array_spec *as;
|
||||
lval = gfc_get_expr ();
|
||||
lval->expr_type = EXPR_VARIABLE;
|
||||
lval->where = sym->declared_at;
|
||||
@ -4059,10 +4060,10 @@ gfc_lval_expr_from_sym (gfc_symbol *sym)
|
||||
lval->symtree = gfc_find_symtree (sym->ns->sym_root, sym->name);
|
||||
|
||||
/* It will always be a full array. */
|
||||
lval->rank = sym->as ? sym->as->rank : 0;
|
||||
as = IS_CLASS_ARRAY (sym) ? CLASS_DATA (sym)->as : sym->as;
|
||||
lval->rank = as ? as->rank : 0;
|
||||
if (lval->rank)
|
||||
gfc_add_full_array_ref (lval, sym->ts.type == BT_CLASS ?
|
||||
CLASS_DATA (sym)->as : sym->as);
|
||||
gfc_add_full_array_ref (lval, as);
|
||||
return lval;
|
||||
}
|
||||
|
||||
|
@ -3210,6 +3210,11 @@ bool gfc_is_finalizable (gfc_symbol *, gfc_expr **);
|
||||
&& CLASS_DATA (sym) \
|
||||
&& CLASS_DATA (sym)->ts.u.derived \
|
||||
&& CLASS_DATA (sym)->ts.u.derived->attr.unlimited_polymorphic)
|
||||
#define IS_CLASS_ARRAY(sym) \
|
||||
(sym->ts.type == BT_CLASS \
|
||||
&& CLASS_DATA (sym) \
|
||||
&& CLASS_DATA (sym)->attr.dimension \
|
||||
&& !CLASS_DATA (sym)->attr.class_pointer)
|
||||
|
||||
/* frontend-passes.c */
|
||||
|
||||
|
@ -2495,11 +2495,14 @@ gfc_add_loop_ss_code (gfc_loopinfo * loop, gfc_ss * ss, bool subscript,
|
||||
case GFC_SS_REFERENCE:
|
||||
/* Scalar argument to elemental procedure. */
|
||||
gfc_init_se (&se, NULL);
|
||||
if (ss_info->can_be_null_ref)
|
||||
if (ss_info->can_be_null_ref || (expr->symtree
|
||||
&& (expr->symtree->n.sym->ts.type == BT_DERIVED
|
||||
|| expr->symtree->n.sym->ts.type == BT_CLASS)))
|
||||
{
|
||||
/* If the actual argument can be absent (in other words, it can
|
||||
be a NULL reference), don't try to evaluate it; pass instead
|
||||
the reference directly. */
|
||||
the reference directly. The reference is also needed when
|
||||
expr is of type class or derived. */
|
||||
gfc_conv_expr_reference (&se, expr);
|
||||
}
|
||||
else
|
||||
@ -3046,7 +3049,14 @@ build_class_array_ref (gfc_se *se, tree base, tree index)
|
||||
return false;
|
||||
}
|
||||
else if (class_ref == NULL)
|
||||
decl = expr->symtree->n.sym->backend_decl;
|
||||
{
|
||||
decl = expr->symtree->n.sym->backend_decl;
|
||||
/* For class arrays the tree containing the class is stored in
|
||||
GFC_DECL_SAVED_DESCRIPTOR of the sym's backend_decl.
|
||||
For all others it's sym's backend_decl directly. */
|
||||
if (DECL_LANG_SPECIFIC (decl) && GFC_DECL_SAVED_DESCRIPTOR (decl))
|
||||
decl = GFC_DECL_SAVED_DESCRIPTOR (decl);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Remove everything after the last class reference, convert the
|
||||
@ -3155,30 +3165,45 @@ add_to_offset (tree *cst_offset, tree *offset, tree t)
|
||||
|
||||
|
||||
static tree
|
||||
build_array_ref (tree desc, tree offset, tree decl)
|
||||
build_array_ref (tree desc, tree offset, tree decl, tree vptr)
|
||||
{
|
||||
tree tmp;
|
||||
tree type;
|
||||
tree cdecl;
|
||||
bool classarray = false;
|
||||
|
||||
/* For class arrays the class declaration is stored in the saved
|
||||
descriptor. */
|
||||
if (INDIRECT_REF_P (desc)
|
||||
&& DECL_LANG_SPECIFIC (TREE_OPERAND (desc, 0))
|
||||
&& GFC_DECL_SAVED_DESCRIPTOR (TREE_OPERAND (desc, 0)))
|
||||
cdecl = gfc_class_data_get (GFC_DECL_SAVED_DESCRIPTOR (
|
||||
TREE_OPERAND (desc, 0)));
|
||||
else
|
||||
cdecl = desc;
|
||||
|
||||
/* Class container types do not always have the GFC_CLASS_TYPE_P
|
||||
but the canonical type does. */
|
||||
if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc))
|
||||
&& TREE_CODE (desc) == COMPONENT_REF)
|
||||
if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (cdecl))
|
||||
&& TREE_CODE (cdecl) == COMPONENT_REF)
|
||||
{
|
||||
type = TREE_TYPE (TREE_OPERAND (desc, 0));
|
||||
type = TREE_TYPE (TREE_OPERAND (cdecl, 0));
|
||||
if (TYPE_CANONICAL (type)
|
||||
&& GFC_CLASS_TYPE_P (TYPE_CANONICAL (type)))
|
||||
type = TYPE_CANONICAL (type);
|
||||
{
|
||||
type = TREE_TYPE (desc);
|
||||
classarray = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
type = NULL;
|
||||
|
||||
/* Class array references need special treatment because the assigned
|
||||
type size needs to be used to point to the element. */
|
||||
if (type && GFC_CLASS_TYPE_P (type))
|
||||
if (classarray)
|
||||
{
|
||||
type = gfc_get_element_type (TREE_TYPE (desc));
|
||||
tmp = TREE_OPERAND (desc, 0);
|
||||
type = gfc_get_element_type (type);
|
||||
tmp = TREE_OPERAND (cdecl, 0);
|
||||
tmp = gfc_get_class_array_ref (offset, tmp);
|
||||
tmp = fold_convert (build_pointer_type (type), tmp);
|
||||
tmp = build_fold_indirect_ref_loc (input_location, tmp);
|
||||
@ -3187,7 +3212,7 @@ build_array_ref (tree desc, tree offset, tree decl)
|
||||
|
||||
tmp = gfc_conv_array_data (desc);
|
||||
tmp = build_fold_indirect_ref_loc (input_location, tmp);
|
||||
tmp = gfc_build_array_ref (tmp, offset, decl);
|
||||
tmp = gfc_build_array_ref (tmp, offset, decl, vptr);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
@ -3350,7 +3375,8 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_expr *expr,
|
||||
offset = fold_build2_loc (input_location, PLUS_EXPR,
|
||||
gfc_array_index_type, offset, cst_offset);
|
||||
|
||||
se->expr = build_array_ref (se->expr, offset, sym->backend_decl);
|
||||
se->expr = build_array_ref (se->expr, offset, sym->ts.type == BT_CLASS ?
|
||||
NULL_TREE : sym->backend_decl, se->class_vptr);
|
||||
}
|
||||
|
||||
|
||||
@ -5570,7 +5596,7 @@ gfc_trans_array_cobounds (tree type, stmtblock_t * pblock,
|
||||
gfc_se se;
|
||||
gfc_array_spec *as;
|
||||
|
||||
as = sym->as;
|
||||
as = IS_CLASS_ARRAY (sym) ? CLASS_DATA (sym)->as : sym->as;
|
||||
|
||||
for (dim = as->rank; dim < as->rank + as->corank; dim++)
|
||||
{
|
||||
@ -5613,7 +5639,7 @@ gfc_trans_array_bounds (tree type, gfc_symbol * sym, tree * poffset,
|
||||
|
||||
int dim;
|
||||
|
||||
as = sym->as;
|
||||
as = IS_CLASS_ARRAY (sym) ? CLASS_DATA (sym)->as : sym->as;
|
||||
|
||||
size = gfc_index_one_node;
|
||||
offset = gfc_index_zero_node;
|
||||
@ -5900,12 +5926,17 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc,
|
||||
int checkparm;
|
||||
int no_repack;
|
||||
bool optional_arg;
|
||||
gfc_array_spec *as;
|
||||
bool is_classarray = IS_CLASS_ARRAY (sym);
|
||||
|
||||
/* Do nothing for pointer and allocatable arrays. */
|
||||
if (sym->attr.pointer || sym->attr.allocatable)
|
||||
if ((sym->ts.type != BT_CLASS && sym->attr.pointer)
|
||||
|| (sym->ts.type == BT_CLASS && CLASS_DATA (sym)->attr.class_pointer)
|
||||
|| sym->attr.allocatable
|
||||
|| (is_classarray && CLASS_DATA (sym)->attr.allocatable))
|
||||
return;
|
||||
|
||||
if (sym->attr.dummy && gfc_is_nodesc_array (sym))
|
||||
if (!is_classarray && sym->attr.dummy && gfc_is_nodesc_array (sym))
|
||||
{
|
||||
gfc_trans_g77_array (sym, block);
|
||||
return;
|
||||
@ -5918,14 +5949,20 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc,
|
||||
type = TREE_TYPE (tmpdesc);
|
||||
gcc_assert (GFC_ARRAY_TYPE_P (type));
|
||||
dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
|
||||
dumdesc = build_fold_indirect_ref_loc (input_location, dumdesc);
|
||||
if (is_classarray)
|
||||
/* For a class array the dummy array descriptor is in the _class
|
||||
component. */
|
||||
dumdesc = gfc_class_data_get (dumdesc);
|
||||
else
|
||||
dumdesc = build_fold_indirect_ref_loc (input_location, dumdesc);
|
||||
as = IS_CLASS_ARRAY (sym) ? CLASS_DATA (sym)->as : sym->as;
|
||||
gfc_start_block (&init);
|
||||
|
||||
if (sym->ts.type == BT_CHARACTER
|
||||
&& TREE_CODE (sym->ts.u.cl->backend_decl) == VAR_DECL)
|
||||
gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
|
||||
|
||||
checkparm = (sym->as->type == AS_EXPLICIT
|
||||
checkparm = (as->type == AS_EXPLICIT
|
||||
&& (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS));
|
||||
|
||||
no_repack = !(GFC_DECL_PACKED_ARRAY (tmpdesc)
|
||||
@ -6001,9 +6038,9 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc,
|
||||
size = gfc_index_one_node;
|
||||
|
||||
/* Evaluate the bounds of the array. */
|
||||
for (n = 0; n < sym->as->rank; n++)
|
||||
for (n = 0; n < as->rank; n++)
|
||||
{
|
||||
if (checkparm || !sym->as->upper[n])
|
||||
if (checkparm || !as->upper[n])
|
||||
{
|
||||
/* Get the bounds of the actual parameter. */
|
||||
dubound = gfc_conv_descriptor_ubound_get (dumdesc, gfc_rank_cst[n]);
|
||||
@ -6019,7 +6056,7 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc,
|
||||
if (!INTEGER_CST_P (lbound))
|
||||
{
|
||||
gfc_init_se (&se, NULL);
|
||||
gfc_conv_expr_type (&se, sym->as->lower[n],
|
||||
gfc_conv_expr_type (&se, as->lower[n],
|
||||
gfc_array_index_type);
|
||||
gfc_add_block_to_block (&init, &se.pre);
|
||||
gfc_add_modify (&init, lbound, se.expr);
|
||||
@ -6027,13 +6064,13 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc,
|
||||
|
||||
ubound = GFC_TYPE_ARRAY_UBOUND (type, n);
|
||||
/* Set the desired upper bound. */
|
||||
if (sym->as->upper[n])
|
||||
if (as->upper[n])
|
||||
{
|
||||
/* We know what we want the upper bound to be. */
|
||||
if (!INTEGER_CST_P (ubound))
|
||||
{
|
||||
gfc_init_se (&se, NULL);
|
||||
gfc_conv_expr_type (&se, sym->as->upper[n],
|
||||
gfc_conv_expr_type (&se, as->upper[n],
|
||||
gfc_array_index_type);
|
||||
gfc_add_block_to_block (&init, &se.pre);
|
||||
gfc_add_modify (&init, ubound, se.expr);
|
||||
@ -6086,7 +6123,7 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc,
|
||||
gfc_array_index_type, offset, tmp);
|
||||
|
||||
/* The size of this dimension, and the stride of the next. */
|
||||
if (n + 1 < sym->as->rank)
|
||||
if (n + 1 < as->rank)
|
||||
{
|
||||
stride = GFC_TYPE_ARRAY_STRIDE (type, n + 1);
|
||||
|
||||
@ -6234,7 +6271,7 @@ gfc_get_dataptr_offset (stmtblock_t *block, tree parm, tree desc, tree offset,
|
||||
return;
|
||||
}
|
||||
|
||||
tmp = build_array_ref (desc, offset, NULL);
|
||||
tmp = build_array_ref (desc, offset, NULL, NULL);
|
||||
|
||||
/* Offset the data pointer for pointer assignments from arrays with
|
||||
subreferences; e.g. my_integer => my_type(:)%integer_component. */
|
||||
@ -6789,6 +6826,7 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
|
||||
tree from;
|
||||
tree to;
|
||||
tree base;
|
||||
bool onebased = false;
|
||||
|
||||
ndim = info->ref ? info->ref->u.ar.dimen : ss->dimen;
|
||||
|
||||
@ -6930,6 +6968,7 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
|
||||
gfc_array_index_type, to, tmp);
|
||||
from = gfc_index_one_node;
|
||||
}
|
||||
onebased = integer_onep (from);
|
||||
gfc_conv_descriptor_lbound_set (&loop.pre, parm,
|
||||
gfc_rank_cst[dim], from);
|
||||
|
||||
@ -6986,13 +7025,29 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
|
||||
gfc_get_dataptr_offset (&loop.pre, parm, desc, offset,
|
||||
subref_array_target, expr);
|
||||
|
||||
if (((se->direct_byref || GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
|
||||
&& !se->data_not_needed)
|
||||
|| (se->use_offset && base != NULL_TREE))
|
||||
/* Force the offset to be -1, when the lower bound of the highest
|
||||
dimension is one and the symbol is present and is not a
|
||||
pointer/allocatable or associated. */
|
||||
if (onebased && se->use_offset
|
||||
&& expr->symtree
|
||||
&& !(expr->symtree->n.sym && expr->symtree->n.sym->ts.type == BT_CLASS
|
||||
&& !CLASS_DATA (expr->symtree->n.sym)->attr.class_pointer)
|
||||
&& !expr->symtree->n.sym->attr.allocatable
|
||||
&& !expr->symtree->n.sym->attr.pointer
|
||||
&& !expr->symtree->n.sym->attr.host_assoc
|
||||
&& !expr->symtree->n.sym->attr.use_assoc)
|
||||
{
|
||||
/* Set the offset. */
|
||||
gfc_conv_descriptor_offset_set (&loop.pre, parm, base);
|
||||
/* Set the offset to -1. */
|
||||
mpz_t minus_one;
|
||||
mpz_init_set_si (minus_one, -1);
|
||||
tmp = gfc_conv_mpz_to_tree (minus_one, gfc_index_integer_kind);
|
||||
gfc_conv_descriptor_offset_set (&loop.pre, parm, tmp);
|
||||
}
|
||||
else if (((se->direct_byref || GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
|
||||
&& !se->data_not_needed)
|
||||
|| (se->use_offset && base != NULL_TREE))
|
||||
/* Set the offset depending on base. */
|
||||
gfc_conv_descriptor_offset_set (&loop.pre, parm, base);
|
||||
else
|
||||
{
|
||||
/* Only the callee knows what the correct offset it, so just set
|
||||
|
@ -812,8 +812,13 @@ gfc_build_qualified_array (tree decl, gfc_symbol * sym)
|
||||
int dim;
|
||||
int nest;
|
||||
gfc_namespace* procns;
|
||||
symbol_attribute *array_attr;
|
||||
gfc_array_spec *as;
|
||||
bool is_classarray = IS_CLASS_ARRAY (sym);
|
||||
|
||||
type = TREE_TYPE (decl);
|
||||
array_attr = is_classarray ? &CLASS_DATA (sym)->attr : &sym->attr;
|
||||
as = is_classarray ? CLASS_DATA (sym)->as : sym->as;
|
||||
|
||||
/* We just use the descriptor, if there is one. */
|
||||
if (GFC_DESCRIPTOR_TYPE_P (type))
|
||||
@ -824,8 +829,8 @@ gfc_build_qualified_array (tree decl, gfc_symbol * sym)
|
||||
nest = (procns->proc_name->backend_decl != current_function_decl)
|
||||
&& !sym->attr.contained;
|
||||
|
||||
if (sym->attr.codimension && flag_coarray == GFC_FCOARRAY_LIB
|
||||
&& sym->as->type != AS_ASSUMED_SHAPE
|
||||
if (array_attr->codimension && flag_coarray == GFC_FCOARRAY_LIB
|
||||
&& as->type != AS_ASSUMED_SHAPE
|
||||
&& GFC_TYPE_ARRAY_CAF_TOKEN (type) == NULL_TREE)
|
||||
{
|
||||
tree token;
|
||||
@ -878,8 +883,8 @@ gfc_build_qualified_array (tree decl, gfc_symbol * sym)
|
||||
}
|
||||
/* Don't try to use the unknown bound for assumed shape arrays. */
|
||||
if (GFC_TYPE_ARRAY_UBOUND (type, dim) == NULL_TREE
|
||||
&& (sym->as->type != AS_ASSUMED_SIZE
|
||||
|| dim < GFC_TYPE_ARRAY_RANK (type) - 1))
|
||||
&& (as->type != AS_ASSUMED_SIZE
|
||||
|| dim < GFC_TYPE_ARRAY_RANK (type) - 1))
|
||||
{
|
||||
GFC_TYPE_ARRAY_UBOUND (type, dim) = create_index_var ("ubound", nest);
|
||||
TREE_NO_WARNING (GFC_TYPE_ARRAY_UBOUND (type, dim)) = 1;
|
||||
@ -920,7 +925,7 @@ gfc_build_qualified_array (tree decl, gfc_symbol * sym)
|
||||
}
|
||||
|
||||
if (GFC_TYPE_ARRAY_SIZE (type) == NULL_TREE
|
||||
&& sym->as->type != AS_ASSUMED_SIZE)
|
||||
&& as->type != AS_ASSUMED_SIZE)
|
||||
{
|
||||
GFC_TYPE_ARRAY_SIZE (type) = create_index_var ("size", nest);
|
||||
TREE_NO_WARNING (GFC_TYPE_ARRAY_SIZE (type)) = 1;
|
||||
@ -947,12 +952,12 @@ gfc_build_qualified_array (tree decl, gfc_symbol * sym)
|
||||
}
|
||||
|
||||
if (TYPE_NAME (type) != NULL_TREE
|
||||
&& GFC_TYPE_ARRAY_UBOUND (type, sym->as->rank - 1) != NULL_TREE
|
||||
&& TREE_CODE (GFC_TYPE_ARRAY_UBOUND (type, sym->as->rank - 1)) == VAR_DECL)
|
||||
&& GFC_TYPE_ARRAY_UBOUND (type, as->rank - 1) != NULL_TREE
|
||||
&& TREE_CODE (GFC_TYPE_ARRAY_UBOUND (type, as->rank - 1)) == VAR_DECL)
|
||||
{
|
||||
tree gtype = DECL_ORIGINAL_TYPE (TYPE_NAME (type));
|
||||
|
||||
for (dim = 0; dim < sym->as->rank - 1; dim++)
|
||||
for (dim = 0; dim < as->rank - 1; dim++)
|
||||
{
|
||||
gcc_assert (TREE_CODE (gtype) == ARRAY_TYPE);
|
||||
gtype = TREE_TYPE (gtype);
|
||||
@ -966,7 +971,7 @@ gfc_build_qualified_array (tree decl, gfc_symbol * sym)
|
||||
{
|
||||
tree gtype = TREE_TYPE (type), rtype, type_decl;
|
||||
|
||||
for (dim = sym->as->rank - 1; dim >= 0; dim--)
|
||||
for (dim = as->rank - 1; dim >= 0; dim--)
|
||||
{
|
||||
tree lbound, ubound;
|
||||
lbound = GFC_TYPE_ARRAY_LBOUND (type, dim);
|
||||
@ -1014,41 +1019,56 @@ gfc_build_dummy_array_decl (gfc_symbol * sym, tree dummy)
|
||||
tree decl;
|
||||
tree type;
|
||||
gfc_array_spec *as;
|
||||
symbol_attribute *array_attr;
|
||||
char *name;
|
||||
gfc_packed packed;
|
||||
int n;
|
||||
bool known_size;
|
||||
bool is_classarray = IS_CLASS_ARRAY (sym);
|
||||
|
||||
if (sym->attr.pointer || sym->attr.allocatable
|
||||
|| (sym->as && sym->as->type == AS_ASSUMED_RANK))
|
||||
/* Use the array as and attr. */
|
||||
as = is_classarray ? CLASS_DATA (sym)->as : sym->as;
|
||||
array_attr = is_classarray ? &CLASS_DATA (sym)->attr : &sym->attr;
|
||||
|
||||
/* The dummy is returned for pointer, allocatable or assumed rank arrays.
|
||||
For class arrays the information if sym is an allocatable or pointer
|
||||
object needs to be checked explicitly (IS_CLASS_ARRAY can be false for
|
||||
too many reasons to be of use here). */
|
||||
if ((sym->ts.type != BT_CLASS && sym->attr.pointer)
|
||||
|| (sym->ts.type == BT_CLASS && CLASS_DATA (sym)->attr.class_pointer)
|
||||
|| array_attr->allocatable
|
||||
|| (as && as->type == AS_ASSUMED_RANK))
|
||||
return dummy;
|
||||
|
||||
/* Add to list of variables if not a fake result variable. */
|
||||
/* Add to list of variables if not a fake result variable.
|
||||
These symbols are set on the symbol only, not on the class component. */
|
||||
if (sym->attr.result || sym->attr.dummy)
|
||||
gfc_defer_symbol_init (sym);
|
||||
|
||||
type = TREE_TYPE (dummy);
|
||||
/* For a class array the array descriptor is in the _data component, while
|
||||
for a regular array the TREE_TYPE of the dummy is a pointer to the
|
||||
descriptor. */
|
||||
type = TREE_TYPE (is_classarray ? gfc_class_data_get (dummy)
|
||||
: TREE_TYPE (dummy));
|
||||
/* type now is the array descriptor w/o any indirection. */
|
||||
gcc_assert (TREE_CODE (dummy) == PARM_DECL
|
||||
&& POINTER_TYPE_P (type));
|
||||
&& POINTER_TYPE_P (TREE_TYPE (dummy)));
|
||||
|
||||
/* Do we know the element size? */
|
||||
known_size = sym->ts.type != BT_CHARACTER
|
||||
|| INTEGER_CST_P (sym->ts.u.cl->backend_decl);
|
||||
|
||||
if (known_size && !GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (type)))
|
||||
if (known_size && !GFC_DESCRIPTOR_TYPE_P (type))
|
||||
{
|
||||
/* For descriptorless arrays with known element size the actual
|
||||
argument is sufficient. */
|
||||
gcc_assert (GFC_ARRAY_TYPE_P (type));
|
||||
gfc_build_qualified_array (dummy, sym);
|
||||
return dummy;
|
||||
}
|
||||
|
||||
type = TREE_TYPE (type);
|
||||
if (GFC_DESCRIPTOR_TYPE_P (type))
|
||||
{
|
||||
/* Create a descriptorless array pointer. */
|
||||
as = sym->as;
|
||||
packed = PACKED_NO;
|
||||
|
||||
/* Even when -frepack-arrays is used, symbols with TARGET attribute
|
||||
@ -1079,8 +1099,11 @@ gfc_build_dummy_array_decl (gfc_symbol * sym, tree dummy)
|
||||
packed = PACKED_PARTIAL;
|
||||
}
|
||||
|
||||
type = gfc_typenode_for_spec (&sym->ts);
|
||||
type = gfc_get_nodesc_array_type (type, sym->as, packed,
|
||||
/* For classarrays the element type is required, but
|
||||
gfc_typenode_for_spec () returns the array descriptor. */
|
||||
type = is_classarray ? gfc_get_element_type (type)
|
||||
: gfc_typenode_for_spec (&sym->ts);
|
||||
type = gfc_get_nodesc_array_type (type, as, packed,
|
||||
!sym->attr.target);
|
||||
}
|
||||
else
|
||||
@ -1110,7 +1133,7 @@ gfc_build_dummy_array_decl (gfc_symbol * sym, tree dummy)
|
||||
|
||||
/* We should never get deferred shape arrays here. We used to because of
|
||||
frontend bugs. */
|
||||
gcc_assert (sym->as->type != AS_DEFERRED);
|
||||
gcc_assert (as->type != AS_DEFERRED);
|
||||
|
||||
if (packed == PACKED_PARTIAL)
|
||||
GFC_DECL_PARTIAL_PACKED_ARRAY (decl) = 1;
|
||||
@ -1429,13 +1452,30 @@ gfc_get_symbol_decl (gfc_symbol * sym)
|
||||
sym->backend_decl = decl;
|
||||
}
|
||||
|
||||
/* Returning the descriptor for dummy class arrays is hazardous, because
|
||||
some caller is expecting an expression to apply the component refs to.
|
||||
Therefore the descriptor is only created and stored in
|
||||
sym->backend_decl's GFC_DECL_SAVED_DESCRIPTOR. The caller is then
|
||||
responsible to extract it from there, when the descriptor is
|
||||
desired. */
|
||||
if (IS_CLASS_ARRAY (sym)
|
||||
&& (!DECL_LANG_SPECIFIC (sym->backend_decl)
|
||||
|| !GFC_DECL_SAVED_DESCRIPTOR (sym->backend_decl)))
|
||||
{
|
||||
decl = gfc_build_dummy_array_decl (sym, sym->backend_decl);
|
||||
/* Prevent the dummy from being detected as unused if it is copied. */
|
||||
if (sym->backend_decl != NULL && decl != sym->backend_decl)
|
||||
DECL_ARTIFICIAL (sym->backend_decl) = 1;
|
||||
sym->backend_decl = decl;
|
||||
}
|
||||
|
||||
TREE_USED (sym->backend_decl) = 1;
|
||||
if (sym->attr.assign && GFC_DECL_ASSIGN (sym->backend_decl) == 0)
|
||||
{
|
||||
gfc_add_assign_aux_vars (sym);
|
||||
}
|
||||
|
||||
if (sym->attr.dimension
|
||||
if ((sym->attr.dimension || IS_CLASS_ARRAY (sym))
|
||||
&& DECL_LANG_SPECIFIC (sym->backend_decl)
|
||||
&& GFC_DECL_SAVED_DESCRIPTOR (sym->backend_decl)
|
||||
&& DECL_CONTEXT (sym->backend_decl) != current_function_decl)
|
||||
@ -3976,18 +4016,31 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block)
|
||||
= gfc_class_set_static_fields (sym->backend_decl, vptr, tmp);
|
||||
TREE_CONSTANT (DECL_INITIAL (sym->backend_decl)) = 1;
|
||||
}
|
||||
else if (sym->attr.dimension || sym->attr.codimension)
|
||||
else if (sym->attr.dimension || sym->attr.codimension
|
||||
|| (IS_CLASS_ARRAY (sym) && !CLASS_DATA (sym)->attr.allocatable))
|
||||
{
|
||||
/* Assumed-size Cray pointees need to be treated as AS_EXPLICIT. */
|
||||
array_type tmp = sym->as->type;
|
||||
if (tmp == AS_ASSUMED_SIZE && sym->as->cp_was_assumed)
|
||||
tmp = AS_EXPLICIT;
|
||||
switch (tmp)
|
||||
bool is_classarray = IS_CLASS_ARRAY (sym);
|
||||
symbol_attribute *array_attr;
|
||||
gfc_array_spec *as;
|
||||
array_type tmp;
|
||||
|
||||
array_attr = is_classarray ? &CLASS_DATA (sym)->attr : &sym->attr;
|
||||
as = is_classarray ? CLASS_DATA (sym)->as : sym->as;
|
||||
/* Assumed-size Cray pointees need to be treated as AS_EXPLICIT. */
|
||||
tmp = as->type;
|
||||
if (tmp == AS_ASSUMED_SIZE && as->cp_was_assumed)
|
||||
tmp = AS_EXPLICIT;
|
||||
switch (tmp)
|
||||
{
|
||||
case AS_EXPLICIT:
|
||||
if (sym->attr.dummy || sym->attr.result)
|
||||
gfc_trans_dummy_array_bias (sym, sym->backend_decl, block);
|
||||
else if (sym->attr.pointer || sym->attr.allocatable)
|
||||
/* Allocatable and pointer arrays need to processed
|
||||
explicitly. */
|
||||
else if ((sym->ts.type != BT_CLASS && sym->attr.pointer)
|
||||
|| (sym->ts.type == BT_CLASS
|
||||
&& CLASS_DATA (sym)->attr.class_pointer)
|
||||
|| array_attr->allocatable)
|
||||
{
|
||||
if (TREE_STATIC (sym->backend_decl))
|
||||
{
|
||||
@ -4002,7 +4055,8 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block)
|
||||
gfc_trans_deferred_array (sym, block);
|
||||
}
|
||||
}
|
||||
else if (sym->attr.codimension && TREE_STATIC (sym->backend_decl))
|
||||
else if (sym->attr.codimension
|
||||
&& TREE_STATIC (sym->backend_decl))
|
||||
{
|
||||
gfc_init_block (&tmpblock);
|
||||
gfc_trans_array_cobounds (TREE_TYPE (sym->backend_decl),
|
||||
@ -4041,7 +4095,7 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block)
|
||||
|
||||
case AS_ASSUMED_SIZE:
|
||||
/* Must be a dummy parameter. */
|
||||
gcc_assert (sym->attr.dummy || sym->as->cp_was_assumed);
|
||||
gcc_assert (sym->attr.dummy || as->cp_was_assumed);
|
||||
|
||||
/* We should always pass assumed size arrays the g77 way. */
|
||||
if (sym->attr.dummy)
|
||||
@ -4103,6 +4157,7 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block)
|
||||
}
|
||||
else
|
||||
{
|
||||
se.descriptor_only = 1;
|
||||
gfc_conv_expr (&se, e);
|
||||
descriptor = se.expr;
|
||||
se.expr = gfc_conv_descriptor_data_addr (se.expr);
|
||||
|
@ -149,6 +149,11 @@ tree
|
||||
gfc_class_vptr_get (tree decl)
|
||||
{
|
||||
tree vptr;
|
||||
/* For class arrays decl may be a temporary descriptor handle, the vptr is
|
||||
then available through the saved descriptor. */
|
||||
if (TREE_CODE (decl) == VAR_DECL && DECL_LANG_SPECIFIC (decl)
|
||||
&& GFC_DECL_SAVED_DESCRIPTOR (decl))
|
||||
decl = GFC_DECL_SAVED_DESCRIPTOR (decl);
|
||||
if (POINTER_TYPE_P (TREE_TYPE (decl)))
|
||||
decl = build_fold_indirect_ref_loc (input_location, decl);
|
||||
vptr = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (decl)),
|
||||
@ -163,6 +168,11 @@ tree
|
||||
gfc_class_len_get (tree decl)
|
||||
{
|
||||
tree len;
|
||||
/* For class arrays decl may be a temporary descriptor handle, the len is
|
||||
then available through the saved descriptor. */
|
||||
if (TREE_CODE (decl) == VAR_DECL && DECL_LANG_SPECIFIC (decl)
|
||||
&& GFC_DECL_SAVED_DESCRIPTOR (decl))
|
||||
decl = GFC_DECL_SAVED_DESCRIPTOR (decl);
|
||||
if (POINTER_TYPE_P (TREE_TYPE (decl)))
|
||||
decl = build_fold_indirect_ref_loc (input_location, decl);
|
||||
len = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (decl)),
|
||||
@ -804,6 +814,16 @@ gfc_conv_intrinsic_to_class (gfc_se *parmse, gfc_expr *e,
|
||||
|
||||
gfc_add_modify (&parmse->pre, ctree, tmp);
|
||||
}
|
||||
else if (class_ts.type == BT_CLASS
|
||||
&& class_ts.u.derived->components
|
||||
&& class_ts.u.derived->components->ts.u
|
||||
.derived->attr.unlimited_polymorphic)
|
||||
{
|
||||
ctree = gfc_class_len_get (var);
|
||||
gfc_add_modify (&parmse->pre, ctree,
|
||||
fold_convert (TREE_TYPE (ctree),
|
||||
integer_zero_node));
|
||||
}
|
||||
/* Pass the address of the class object. */
|
||||
parmse->expr = gfc_build_addr_expr (NULL_TREE, var);
|
||||
}
|
||||
@ -830,6 +850,7 @@ gfc_conv_class_to_class (gfc_se *parmse, gfc_expr *e, gfc_typespec class_ts,
|
||||
tree tmp;
|
||||
tree vptr;
|
||||
tree cond = NULL_TREE;
|
||||
tree slen = NULL_TREE;
|
||||
gfc_ref *ref;
|
||||
gfc_ref *class_ref;
|
||||
stmtblock_t block;
|
||||
@ -921,7 +942,12 @@ gfc_conv_class_to_class (gfc_se *parmse, gfc_expr *e, gfc_typespec class_ts,
|
||||
tmp = NULL_TREE;
|
||||
if (class_ref == NULL
|
||||
&& e->symtree && e->symtree->n.sym->ts.type == BT_CLASS)
|
||||
tmp = e->symtree->n.sym->backend_decl;
|
||||
{
|
||||
tmp = e->symtree->n.sym->backend_decl;
|
||||
if (DECL_LANG_SPECIFIC (tmp) && GFC_DECL_SAVED_DESCRIPTOR (tmp))
|
||||
tmp = GFC_DECL_SAVED_DESCRIPTOR (tmp);
|
||||
slen = integer_zero_node;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Remove everything after the last class reference, convert the
|
||||
@ -933,6 +959,7 @@ gfc_conv_class_to_class (gfc_se *parmse, gfc_expr *e, gfc_typespec class_ts,
|
||||
gfc_conv_expr (&tmpse, e);
|
||||
class_ref->next = ref;
|
||||
tmp = tmpse.expr;
|
||||
slen = tmpse.string_length;
|
||||
}
|
||||
|
||||
gcc_assert (tmp != NULL_TREE);
|
||||
@ -951,11 +978,38 @@ gfc_conv_class_to_class (gfc_se *parmse, gfc_expr *e, gfc_typespec class_ts,
|
||||
gfc_add_modify (&parmse->post, vptr,
|
||||
fold_convert (TREE_TYPE (vptr), ctree));
|
||||
|
||||
/* For unlimited polymorphic objects also set the _len component. */
|
||||
if (class_ts.type == BT_CLASS
|
||||
&& class_ts.u.derived->components
|
||||
&& class_ts.u.derived->components->ts.u
|
||||
.derived->attr.unlimited_polymorphic)
|
||||
{
|
||||
ctree = gfc_class_len_get (var);
|
||||
if (UNLIMITED_POLY (e))
|
||||
tmp = gfc_class_len_get (tmp);
|
||||
else if (e->ts.type == BT_CHARACTER)
|
||||
{
|
||||
gcc_assert (slen != NULL_TREE);
|
||||
tmp = slen;
|
||||
}
|
||||
else
|
||||
tmp = integer_zero_node;
|
||||
gfc_add_modify (&parmse->pre, ctree,
|
||||
fold_convert (TREE_TYPE (ctree), tmp));
|
||||
}
|
||||
|
||||
if (optional)
|
||||
{
|
||||
tree tmp2;
|
||||
|
||||
cond = gfc_conv_expr_present (e->symtree->n.sym);
|
||||
/* parmse->pre may contain some preparatory instructions for the
|
||||
temporary array descriptor. Those may only be executed when the
|
||||
optional argument is set, therefore add parmse->pre's instructions
|
||||
to block, which is later guarded by an if (optional_arg_given). */
|
||||
gfc_add_block_to_block (&parmse->pre, &block);
|
||||
block.head = parmse->pre.head;
|
||||
parmse->pre.head = NULL_TREE;
|
||||
tmp = gfc_finish_block (&block);
|
||||
|
||||
if (optional_alloc_ptr)
|
||||
@ -1042,7 +1096,7 @@ 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);
|
||||
from_data = gfc_class_data_get (from);
|
||||
else
|
||||
from_data = gfc_class_vtab_def_init_get (to);
|
||||
|
||||
@ -1099,7 +1153,8 @@ gfc_copy_class_to_class (tree from, tree to, tree nelems, bool unlimited)
|
||||
gfc_init_block (&ifbody);
|
||||
gfc_add_block_to_block (&ifbody, &loop.pre);
|
||||
stdcopy = gfc_finish_block (&ifbody);
|
||||
if (unlimited)
|
||||
/* In initialization mode from_len is a constant zero. */
|
||||
if (unlimited && !integer_zerop (from_len))
|
||||
{
|
||||
vec_safe_push (args, from_len);
|
||||
vec_safe_push (args, to_len);
|
||||
@ -1141,7 +1196,8 @@ gfc_copy_class_to_class (tree from, tree to, tree nelems, bool unlimited)
|
||||
vec_safe_push (args, to_data);
|
||||
stdcopy = build_call_vec (fcn_type, fcn, args);
|
||||
|
||||
if (unlimited)
|
||||
/* In initialization mode from_len is a constant zero. */
|
||||
if (unlimited && !integer_zerop (from_len))
|
||||
{
|
||||
vec_safe_push (args, from_len);
|
||||
vec_safe_push (args, to_len);
|
||||
@ -1156,6 +1212,18 @@ gfc_copy_class_to_class (tree from, tree to, tree nelems, bool unlimited)
|
||||
tmp = stdcopy;
|
||||
}
|
||||
|
||||
/* Only copy _def_init to to_data, when it is not a NULL-pointer. */
|
||||
if (from == NULL_TREE)
|
||||
{
|
||||
tree cond;
|
||||
cond = fold_build2_loc (input_location, NE_EXPR,
|
||||
boolean_type_node,
|
||||
from_data, null_pointer_node);
|
||||
tmp = fold_build3_loc (input_location, COND_EXPR,
|
||||
void_type_node, cond,
|
||||
tmp, build_empty_stmt (input_location));
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
@ -1229,6 +1297,8 @@ gfc_trans_class_init_assign (gfc_code *code)
|
||||
been referenced. */
|
||||
gfc_get_derived_type (rhs->ts.u.derived);
|
||||
gfc_add_def_init_component (rhs);
|
||||
/* The _def_init is always scalar. */
|
||||
rhs->rank = 0;
|
||||
|
||||
if (code->expr1->ts.type == BT_CLASS
|
||||
&& CLASS_DATA (code->expr1)->attr.dimension)
|
||||
@ -2203,6 +2273,16 @@ gfc_conv_component_ref (gfc_se * se, gfc_ref * ref)
|
||||
field = f2;
|
||||
}
|
||||
|
||||
if (ref->u.c.sym && ref->u.c.sym->ts.type == BT_CLASS
|
||||
&& strcmp ("_data", c->name) == 0)
|
||||
{
|
||||
/* Found a ref to the _data component. Store the associated ref to
|
||||
the vptr in se->class_vptr. */
|
||||
se->class_vptr = gfc_class_vptr_get (decl);
|
||||
}
|
||||
else
|
||||
se->class_vptr = NULL_TREE;
|
||||
|
||||
tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
|
||||
decl, field, NULL_TREE);
|
||||
|
||||
@ -2284,8 +2364,11 @@ gfc_conv_variable (gfc_se * se, gfc_expr * expr)
|
||||
bool return_value;
|
||||
bool alternate_entry;
|
||||
bool entry_master;
|
||||
bool is_classarray;
|
||||
bool first_time = true;
|
||||
|
||||
sym = expr->symtree->n.sym;
|
||||
is_classarray = IS_CLASS_ARRAY (sym);
|
||||
ss = se->ss;
|
||||
if (ss != NULL)
|
||||
{
|
||||
@ -2389,9 +2472,24 @@ gfc_conv_variable (gfc_se * se, gfc_expr * expr)
|
||||
}
|
||||
else if (!sym->attr.value)
|
||||
{
|
||||
/* Dereference temporaries for class array dummy arguments. */
|
||||
if (sym->attr.dummy && is_classarray
|
||||
&& GFC_ARRAY_TYPE_P (TREE_TYPE (se->expr)))
|
||||
{
|
||||
if (!se->descriptor_only)
|
||||
se->expr = GFC_DECL_SAVED_DESCRIPTOR (se->expr);
|
||||
|
||||
se->expr = build_fold_indirect_ref_loc (input_location,
|
||||
se->expr);
|
||||
}
|
||||
|
||||
/* Dereference non-character scalar dummy arguments. */
|
||||
if (sym->attr.dummy && !sym->attr.dimension
|
||||
&& !(sym->attr.codimension && sym->attr.allocatable))
|
||||
&& !(sym->attr.codimension && sym->attr.allocatable)
|
||||
&& (sym->ts.type != BT_CLASS
|
||||
|| (!CLASS_DATA (sym)->attr.dimension
|
||||
&& !(CLASS_DATA (sym)->attr.codimension
|
||||
&& CLASS_DATA (sym)->attr.allocatable))))
|
||||
se->expr = build_fold_indirect_ref_loc (input_location,
|
||||
se->expr);
|
||||
|
||||
@ -2403,11 +2501,12 @@ gfc_conv_variable (gfc_se * se, gfc_expr * expr)
|
||||
se->expr = build_fold_indirect_ref_loc (input_location,
|
||||
se->expr);
|
||||
|
||||
/* Dereference non-character pointer variables.
|
||||
/* Dereference non-character, non-class pointer variables.
|
||||
These must be dummies, results, or scalars. */
|
||||
if ((sym->attr.pointer || sym->attr.allocatable
|
||||
|| gfc_is_associate_pointer (sym)
|
||||
|| (sym->as && sym->as->type == AS_ASSUMED_RANK))
|
||||
if (!is_classarray
|
||||
&& (sym->attr.pointer || sym->attr.allocatable
|
||||
|| gfc_is_associate_pointer (sym)
|
||||
|| (sym->as && sym->as->type == AS_ASSUMED_RANK))
|
||||
&& (sym->attr.dummy
|
||||
|| sym->attr.function
|
||||
|| sym->attr.result
|
||||
@ -2415,6 +2514,32 @@ gfc_conv_variable (gfc_se * se, gfc_expr * expr)
|
||||
&& (!sym->attr.codimension || !sym->attr.allocatable))))
|
||||
se->expr = build_fold_indirect_ref_loc (input_location,
|
||||
se->expr);
|
||||
/* Now treat the class array pointer variables accordingly. */
|
||||
else if (sym->ts.type == BT_CLASS
|
||||
&& sym->attr.dummy
|
||||
&& (CLASS_DATA (sym)->attr.dimension
|
||||
|| CLASS_DATA (sym)->attr.codimension)
|
||||
&& ((CLASS_DATA (sym)->as
|
||||
&& CLASS_DATA (sym)->as->type == AS_ASSUMED_RANK)
|
||||
|| CLASS_DATA (sym)->attr.allocatable
|
||||
|| CLASS_DATA (sym)->attr.class_pointer))
|
||||
se->expr = build_fold_indirect_ref_loc (input_location,
|
||||
se->expr);
|
||||
/* And the case where a non-dummy, non-result, non-function,
|
||||
non-allotable and non-pointer classarray is present. This case was
|
||||
previously covered by the first if, but with introducing the
|
||||
condition !is_classarray there, that case has to be covered
|
||||
explicitly. */
|
||||
else if (sym->ts.type == BT_CLASS
|
||||
&& !sym->attr.dummy
|
||||
&& !sym->attr.function
|
||||
&& !sym->attr.result
|
||||
&& (CLASS_DATA (sym)->attr.dimension
|
||||
|| CLASS_DATA (sym)->attr.codimension)
|
||||
&& !CLASS_DATA (sym)->attr.allocatable
|
||||
&& !CLASS_DATA (sym)->attr.class_pointer)
|
||||
se->expr = build_fold_indirect_ref_loc (input_location,
|
||||
se->expr);
|
||||
}
|
||||
|
||||
ref = expr->ref;
|
||||
@ -2452,6 +2577,18 @@ gfc_conv_variable (gfc_se * se, gfc_expr * expr)
|
||||
break;
|
||||
|
||||
case REF_COMPONENT:
|
||||
if (first_time && is_classarray && sym->attr.dummy
|
||||
&& se->descriptor_only
|
||||
&& !CLASS_DATA (sym)->attr.allocatable
|
||||
&& !CLASS_DATA (sym)->attr.class_pointer
|
||||
&& CLASS_DATA (sym)->as
|
||||
&& CLASS_DATA (sym)->as->type != AS_ASSUMED_RANK
|
||||
&& strcmp ("_data", ref->u.c.component->name) == 0)
|
||||
/* Skip the first ref of a _data component, because for class
|
||||
arrays that one is already done by introducing a temporary
|
||||
array descriptor. */
|
||||
break;
|
||||
|
||||
if (ref->u.c.sym->attr.extension)
|
||||
conv_parent_component_references (se, ref);
|
||||
|
||||
@ -2471,6 +2608,7 @@ gfc_conv_variable (gfc_se * se, gfc_expr * expr)
|
||||
gcc_unreachable ();
|
||||
break;
|
||||
}
|
||||
first_time = false;
|
||||
ref = ref->next;
|
||||
}
|
||||
/* Pointer assignment, allocation or pass by reference. Arrays are handled
|
||||
@ -4597,7 +4735,19 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
|
||||
gfc_init_se (&parmse, se);
|
||||
parm_kind = ELEMENTAL;
|
||||
|
||||
if (fsym && fsym->attr.value)
|
||||
/* For all value functions or polymorphic scalar non-pointer
|
||||
non-allocatable variables use the expression in e directly. This
|
||||
ensures, that initializers of polymorphic entities are correctly
|
||||
copied. */
|
||||
if (fsym && (fsym->attr.value
|
||||
|| (e->expr_type == EXPR_VARIABLE
|
||||
&& fsym->ts.type == BT_DERIVED
|
||||
&& e->ts.type == BT_DERIVED
|
||||
&& !e->ts.u.derived->attr.dimension
|
||||
&& !e->rank
|
||||
&& (!e->symtree
|
||||
|| (!e->symtree->n.sym->attr.allocatable
|
||||
&& !e->symtree->n.sym->attr.pointer)))))
|
||||
gfc_conv_expr (&parmse, e);
|
||||
else
|
||||
gfc_conv_expr_reference (&parmse, e);
|
||||
|
@ -5921,8 +5921,17 @@ gfc_conv_intrinsic_sizeof (gfc_se *se, gfc_expr *expr)
|
||||
}
|
||||
else if (arg->ts.type == BT_CLASS)
|
||||
{
|
||||
if (arg->rank)
|
||||
/* For deferred length arrays, conv_expr_descriptor returns an
|
||||
indirect_ref to the component. */
|
||||
if (arg->rank < 0
|
||||
|| (arg->rank > 0 && !VAR_P (argse.expr)
|
||||
&& GFC_DECL_CLASS (TREE_OPERAND (argse.expr, 0))))
|
||||
byte_size = gfc_class_vtab_size_get (TREE_OPERAND (argse.expr, 0));
|
||||
else if (arg->rank > 0)
|
||||
/* The scalarizer added an additional temp. To get the class' vptr
|
||||
one has to look at the original backend_decl. */
|
||||
byte_size = gfc_class_vtab_size_get (
|
||||
GFC_DECL_SAVED_DESCRIPTOR (arg->symtree->n.sym->backend_decl));
|
||||
else
|
||||
byte_size = gfc_class_vtab_size_get (argse.expr);
|
||||
}
|
||||
@ -6053,7 +6062,11 @@ gfc_conv_intrinsic_storage_size (gfc_se *se, gfc_expr *expr)
|
||||
gfc_conv_expr_descriptor (&argse, arg);
|
||||
if (arg->ts.type == BT_CLASS)
|
||||
{
|
||||
tmp = gfc_class_vtab_size_get (TREE_OPERAND (argse.expr, 0));
|
||||
if (arg->rank > 0)
|
||||
tmp = gfc_class_vtab_size_get (
|
||||
GFC_DECL_SAVED_DESCRIPTOR (arg->symtree->n.sym->backend_decl));
|
||||
else
|
||||
tmp = gfc_class_vtab_size_get (TREE_OPERAND (argse.expr, 0));
|
||||
tmp = fold_convert (result_type, tmp);
|
||||
goto done;
|
||||
}
|
||||
@ -7080,7 +7093,11 @@ gfc_conv_intrinsic_loc (gfc_se * se, gfc_expr * expr)
|
||||
|
||||
arg_expr = expr->value.function.actual->expr;
|
||||
if (arg_expr->rank == 0)
|
||||
gfc_conv_expr_reference (se, arg_expr);
|
||||
{
|
||||
if (arg_expr->ts.type == BT_CLASS)
|
||||
gfc_add_component_ref (arg_expr, "_data");
|
||||
gfc_conv_expr_reference (se, arg_expr);
|
||||
}
|
||||
else
|
||||
gfc_conv_array_parameter (se, arg_expr, true, NULL, NULL, NULL);
|
||||
se->expr = convert (gfc_get_int_type (gfc_index_integer_kind), se->expr);
|
||||
|
@ -1390,12 +1390,29 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
|
||||
|
||||
gfc_init_se (&se, NULL);
|
||||
se.descriptor_only = 1;
|
||||
gfc_conv_expr (&se, e);
|
||||
/* In a select type the (temporary) associate variable shall point to
|
||||
a standard fortran array (lower bound == 1), but conv_expr ()
|
||||
just maps to the input array in the class object, whose lbound may
|
||||
be arbitrary. conv_expr_descriptor solves this by inserting a
|
||||
temporary array descriptor. */
|
||||
gfc_conv_expr_descriptor (&se, e);
|
||||
|
||||
gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr)));
|
||||
gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr))
|
||||
|| GFC_ARRAY_TYPE_P (TREE_TYPE (se.expr)));
|
||||
gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (sym->backend_decl)));
|
||||
|
||||
gfc_add_modify (&se.pre, sym->backend_decl, se.expr);
|
||||
if (GFC_ARRAY_TYPE_P (TREE_TYPE (se.expr)))
|
||||
{
|
||||
if (INDIRECT_REF_P (se.expr))
|
||||
tmp = TREE_OPERAND (se.expr, 0);
|
||||
else
|
||||
tmp = se.expr;
|
||||
|
||||
gfc_add_modify (&se.pre, sym->backend_decl,
|
||||
gfc_class_data_get (GFC_DECL_SAVED_DESCRIPTOR (tmp)));
|
||||
}
|
||||
else
|
||||
gfc_add_modify (&se.pre, sym->backend_decl, se.expr);
|
||||
|
||||
if (unlimited)
|
||||
{
|
||||
@ -1406,7 +1423,7 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
|
||||
gfc_get_dtype (TREE_TYPE (sym->backend_decl)));
|
||||
}
|
||||
|
||||
gfc_add_init_cleanup (block, gfc_finish_block( &se.pre),
|
||||
gfc_add_init_cleanup (block, gfc_finish_block (&se.pre),
|
||||
gfc_finish_block (&se.post));
|
||||
}
|
||||
|
||||
@ -1449,9 +1466,18 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
|
||||
}
|
||||
if (need_len_assign)
|
||||
{
|
||||
/* Get the _len comp from the target expr by stripping _data
|
||||
from it and adding component-ref to _len. */
|
||||
tmp = gfc_class_len_get (TREE_OPERAND (target_expr, 0));
|
||||
if (e->symtree
|
||||
&& DECL_LANG_SPECIFIC (e->symtree->n.sym->backend_decl)
|
||||
&& GFC_DECL_SAVED_DESCRIPTOR (e->symtree->n.sym->backend_decl))
|
||||
/* Use the original class descriptor stored in the saved
|
||||
descriptor to get the target_expr. */
|
||||
target_expr =
|
||||
GFC_DECL_SAVED_DESCRIPTOR (e->symtree->n.sym->backend_decl);
|
||||
else
|
||||
/* Strip the _data component from the target_expr. */
|
||||
target_expr = TREE_OPERAND (target_expr, 0);
|
||||
/* Add a reference to the _len comp to the target expr. */
|
||||
tmp = gfc_class_len_get (target_expr);
|
||||
/* Get the component-ref for the temp structure's _len comp. */
|
||||
charlen = gfc_class_len_get (se.expr);
|
||||
/* Add the assign to the beginning of the the block... */
|
||||
|
@ -1288,25 +1288,35 @@ gfc_get_element_type (tree type)
|
||||
int
|
||||
gfc_is_nodesc_array (gfc_symbol * sym)
|
||||
{
|
||||
gcc_assert (sym->attr.dimension || sym->attr.codimension);
|
||||
symbol_attribute *array_attr;
|
||||
gfc_array_spec *as;
|
||||
bool is_classarray = IS_CLASS_ARRAY (sym);
|
||||
|
||||
array_attr = is_classarray ? &CLASS_DATA (sym)->attr : &sym->attr;
|
||||
as = is_classarray ? CLASS_DATA (sym)->as : sym->as;
|
||||
|
||||
gcc_assert (array_attr->dimension || array_attr->codimension);
|
||||
|
||||
/* We only want local arrays. */
|
||||
if (sym->attr.pointer || sym->attr.allocatable)
|
||||
if ((sym->ts.type != BT_CLASS && sym->attr.pointer)
|
||||
|| (sym->ts.type == BT_CLASS && CLASS_DATA (sym)->attr.class_pointer)
|
||||
|| array_attr->allocatable)
|
||||
return 0;
|
||||
|
||||
/* We want a descriptor for associate-name arrays that do not have an
|
||||
explicitly known shape already. */
|
||||
if (sym->assoc && sym->as->type != AS_EXPLICIT)
|
||||
explicitly known shape already. */
|
||||
if (sym->assoc && as->type != AS_EXPLICIT)
|
||||
return 0;
|
||||
|
||||
/* The dummy is stored in sym and not in the component. */
|
||||
if (sym->attr.dummy)
|
||||
return sym->as->type != AS_ASSUMED_SHAPE
|
||||
&& sym->as->type != AS_ASSUMED_RANK;
|
||||
return as->type != AS_ASSUMED_SHAPE
|
||||
&& as->type != AS_ASSUMED_RANK;
|
||||
|
||||
if (sym->attr.result || sym->attr.function)
|
||||
return 0;
|
||||
|
||||
gcc_assert (sym->as->type == AS_EXPLICIT || sym->as->cp_was_assumed);
|
||||
gcc_assert (as->type == AS_EXPLICIT || as->cp_was_assumed);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -321,7 +321,7 @@ gfc_build_addr_expr (tree type, tree t)
|
||||
/* Build an ARRAY_REF with its natural type. */
|
||||
|
||||
tree
|
||||
gfc_build_array_ref (tree base, tree offset, tree decl)
|
||||
gfc_build_array_ref (tree base, tree offset, tree decl, tree vptr)
|
||||
{
|
||||
tree type = TREE_TYPE (base);
|
||||
tree tmp;
|
||||
@ -353,30 +353,47 @@ gfc_build_array_ref (tree base, tree offset, tree decl)
|
||||
/* If the array reference is to a pointer, whose target contains a
|
||||
subreference, use the span that is stored with the backend decl
|
||||
and reference the element with pointer arithmetic. */
|
||||
if (decl && (TREE_CODE (decl) == FIELD_DECL
|
||||
|| TREE_CODE (decl) == VAR_DECL
|
||||
|| TREE_CODE (decl) == PARM_DECL)
|
||||
&& ((GFC_DECL_SUBREF_ARRAY_P (decl)
|
||||
&& !integer_zerop (GFC_DECL_SPAN(decl)))
|
||||
if ((decl && (TREE_CODE (decl) == FIELD_DECL
|
||||
|| TREE_CODE (decl) == VAR_DECL
|
||||
|| TREE_CODE (decl) == PARM_DECL)
|
||||
&& ((GFC_DECL_SUBREF_ARRAY_P (decl)
|
||||
&& !integer_zerop (GFC_DECL_SPAN (decl)))
|
||||
|| GFC_DECL_CLASS (decl)))
|
||||
|| vptr)
|
||||
{
|
||||
if (GFC_DECL_CLASS (decl))
|
||||
if (decl)
|
||||
{
|
||||
/* Allow for dummy arguments and other good things. */
|
||||
if (POINTER_TYPE_P (TREE_TYPE (decl)))
|
||||
decl = build_fold_indirect_ref_loc (input_location, decl);
|
||||
if (GFC_DECL_CLASS (decl))
|
||||
{
|
||||
/* When a temporary is in place for the class array, then the
|
||||
original class' declaration is stored in the saved
|
||||
descriptor. */
|
||||
if (DECL_LANG_SPECIFIC (decl) && GFC_DECL_SAVED_DESCRIPTOR (decl))
|
||||
decl = GFC_DECL_SAVED_DESCRIPTOR (decl);
|
||||
else
|
||||
{
|
||||
/* Allow for dummy arguments and other good things. */
|
||||
if (POINTER_TYPE_P (TREE_TYPE (decl)))
|
||||
decl = build_fold_indirect_ref_loc (input_location, decl);
|
||||
|
||||
/* Check if '_data' is an array descriptor. If it is not,
|
||||
the array must be one of the components of the class object,
|
||||
so return a normal array reference. */
|
||||
if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (gfc_class_data_get (decl))))
|
||||
return build4_loc (input_location, ARRAY_REF, type, base,
|
||||
offset, NULL_TREE, NULL_TREE);
|
||||
/* Check if '_data' is an array descriptor. If it is not,
|
||||
the array must be one of the components of the class
|
||||
object, so return a normal array reference. */
|
||||
if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (
|
||||
gfc_class_data_get (decl))))
|
||||
return build4_loc (input_location, ARRAY_REF, type, base,
|
||||
offset, NULL_TREE, NULL_TREE);
|
||||
}
|
||||
|
||||
span = gfc_class_vtab_size_get (decl);
|
||||
span = gfc_class_vtab_size_get (decl);
|
||||
}
|
||||
else if (GFC_DECL_SUBREF_ARRAY_P (decl))
|
||||
span = GFC_DECL_SPAN (decl);
|
||||
else
|
||||
gcc_unreachable ();
|
||||
}
|
||||
else if (GFC_DECL_SUBREF_ARRAY_P (decl))
|
||||
span = GFC_DECL_SPAN(decl);
|
||||
else if (vptr)
|
||||
span = gfc_vptr_size_get (vptr);
|
||||
else
|
||||
gcc_unreachable ();
|
||||
|
||||
|
@ -49,6 +49,10 @@ typedef struct gfc_se
|
||||
/* The length of a character string value. */
|
||||
tree string_length;
|
||||
|
||||
/* When expr is a reference to a class object, store its vptr access
|
||||
here. */
|
||||
tree class_vptr;
|
||||
|
||||
/* If set gfc_conv_variable will return an expression for the array
|
||||
descriptor. When set, want_pointer should also be set.
|
||||
If not set scalarizing variables will be substituted. */
|
||||
@ -528,7 +532,7 @@ tree gfc_get_function_decl (gfc_symbol *);
|
||||
tree gfc_build_addr_expr (tree, tree);
|
||||
|
||||
/* Build an ARRAY_REF. */
|
||||
tree gfc_build_array_ref (tree, tree, tree);
|
||||
tree gfc_build_array_ref (tree, tree, tree, tree vptr = NULL_TREE);
|
||||
|
||||
/* Creates a label. Decl is artificial if label_id == NULL_TREE. */
|
||||
tree gfc_build_label_decl (tree);
|
||||
|
@ -1,3 +1,14 @@
|
||||
2015-04-23 Andre Vehreschild <vehre@gmx.de>
|
||||
|
||||
PR fortran/60322
|
||||
* gfortran.dg/class_allocate_19.f03: New test.
|
||||
* gfortran.dg/class_array_20.f03: New test.
|
||||
* gfortran.dg/class_array_21.f03: New test.
|
||||
* gfortran.dg/finalize_10.f90: Corrected scan-trees.
|
||||
* gfortran.dg/finalize_15.f90: Fixing comparision to model
|
||||
initialization correctly.
|
||||
* gfortran.dg/finalize_29.f08: New test.
|
||||
|
||||
2015-04-22 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
|
||||
|
||||
* gcc.target/powerpc/swaps-p8-18.c: New test.
|
||||
|
@ -27,8 +27,8 @@ end subroutine foo
|
||||
! Finalize CLASS + set default init
|
||||
! { dg-final { scan-tree-dump-times "y->_vptr->_final \\(&desc.\[0-9\]+, y->_vptr->_size, 0\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump "__builtin_memcpy \\(\\(void .\\) y->_data, \\(void .\\) y->_vptr->_def_init, \\((unsigned long|unsigned int|character\\(kind=4\\))\\) y->_vptr->_size\\);" "original" } }
|
||||
! { dg-final { scan-tree-dump-times "x->_vptr->_final \\(&x->_data, x->_vptr->_size, 0\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "x->_vptr->_copy \\(x->_vptr->_def_init, &x->_data\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "x->_vptr->_final \\(&parm.\[0-9\]+, x->_vptr->_size, 0\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "x->_vptr->_copy \\(" 1 "original" } }
|
||||
|
||||
! FINALIZE TYPE:
|
||||
! { dg-final { scan-tree-dump-times "parm.\[0-9\]+.data = \\(void \\*\\) &\\(\\*aa.\[0-9\]+\\)\\\[0\\\];" 1 "original" } }
|
||||
|
@ -9,37 +9,37 @@ module m
|
||||
implicit none
|
||||
|
||||
type t1
|
||||
integer :: i
|
||||
integer :: i = 1
|
||||
contains
|
||||
final :: fini_elem
|
||||
end type t1
|
||||
|
||||
type, extends(t1) :: t1e
|
||||
integer :: j
|
||||
integer :: j = 11
|
||||
contains
|
||||
final :: fini_elem2
|
||||
end type t1e
|
||||
|
||||
type t2
|
||||
integer :: i
|
||||
integer :: i = 2
|
||||
contains
|
||||
final :: fini_shape
|
||||
end type t2
|
||||
|
||||
type, extends(t2) :: t2e
|
||||
integer :: j
|
||||
integer :: j = 22
|
||||
contains
|
||||
final :: fini_shape2
|
||||
end type t2e
|
||||
|
||||
type t3
|
||||
integer :: i
|
||||
integer :: i = 3
|
||||
contains
|
||||
final :: fini_explicit
|
||||
end type t3
|
||||
|
||||
type, extends(t3) :: t3e
|
||||
integer :: j
|
||||
integer :: j = 33
|
||||
contains
|
||||
final :: fini_explicit2
|
||||
end type t3e
|
||||
@ -204,31 +204,31 @@ program test
|
||||
|
||||
select type(x)
|
||||
type is (t1e)
|
||||
call check_val(x%i, 1)
|
||||
call check_val(x%j, 100)
|
||||
call check_val(x%i, 1, 1)
|
||||
call check_val(x%j, 100, 11)
|
||||
end select
|
||||
|
||||
select type(y)
|
||||
type is (t2e)
|
||||
call check_val(y%i, 1)
|
||||
call check_val(y%j, 100)
|
||||
call check_val(y%i, 1, 2)
|
||||
call check_val(y%j, 100, 22)
|
||||
end select
|
||||
|
||||
select type(z)
|
||||
type is (t3e)
|
||||
call check_val(z%i, 1)
|
||||
call check_val(z%j, 100)
|
||||
call check_val(z%i, 1, 3)
|
||||
call check_val(z%j, 100, 33)
|
||||
end select
|
||||
|
||||
contains
|
||||
subroutine check_val(x, factor)
|
||||
subroutine check_val(x, factor, val)
|
||||
integer :: x(:,:)
|
||||
integer, value :: factor
|
||||
integer, value :: factor, val
|
||||
integer :: i, j
|
||||
do i = 1, 10
|
||||
do j = 1, 10
|
||||
if (mod (j-1, 2) == 0 .and. mod (i-1, 3) == 0) then
|
||||
if (x(j,i) /= (j + 100*i)*factor*(-13)) call abort ()
|
||||
if (x(j,i) /= val) call abort ()
|
||||
else
|
||||
if (x(j,i) /= (j + 100*i)*factor) call abort ()
|
||||
end if
|
||||
|
Loading…
x
Reference in New Issue
Block a user