aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/trans-stmt.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/fortran/trans-stmt.c')
-rw-r--r--gcc/fortran/trans-stmt.c180
1 files changed, 90 insertions, 90 deletions
diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c
index 69750df..6772a3c 100644
--- a/gcc/fortran/trans-stmt.c
+++ b/gcc/fortran/trans-stmt.c
@@ -5098,6 +5098,8 @@ gfc_trans_allocate (gfc_code * code)
the trees may be the NULL_TREE indicating that this is not
available for expr3's type. */
tree expr3, expr3_vptr, expr3_len, expr3_esize;
+ /* Classify what expr3 stores. */
+ enum { E3_UNSET = 0, E3_SOURCE, E3_MOLD, E3_DESC } e3_is;
stmtblock_t block;
stmtblock_t post;
tree nelems;
@@ -5110,6 +5112,7 @@ gfc_trans_allocate (gfc_code * code)
stat = tmp = memsz = al_vptr = al_len = NULL_TREE;
expr3 = expr3_vptr = expr3_len = expr3_esize = NULL_TREE;
label_errmsg = label_finish = errmsg = errlen = NULL_TREE;
+ e3_is = E3_UNSET;
gfc_init_block (&block);
gfc_init_block (&post);
@@ -5149,16 +5152,14 @@ gfc_trans_allocate (gfc_code * code)
expression. */
if (code->expr3)
{
- bool vtab_needed = false;
- /* expr3_tmp gets the tree when code->expr3.mold is set, i.e.,
- the expression is only needed to get the _vptr, _len a.s.o. */
- tree expr3_tmp = NULL_TREE;
+ bool vtab_needed = false, temp_var_needed = false;
/* Figure whether we need the vtab from expr3. */
for (al = code->ext.alloc.list; !vtab_needed && al != NULL;
al = al->next)
vtab_needed = (al->expr->ts.type == BT_CLASS);
+ gfc_init_se (&se, NULL);
/* When expr3 is a variable, i.e., a very simple expression,
then convert it once here. */
if (code->expr3->expr_type == EXPR_VARIABLE
@@ -5167,31 +5168,25 @@ gfc_trans_allocate (gfc_code * code)
{
if (!code->expr3->mold
|| code->expr3->ts.type == BT_CHARACTER
- || vtab_needed)
+ || vtab_needed
+ || code->ext.alloc.arr_spec_from_expr3)
{
- /* Convert expr3 to a tree. */
- gfc_init_se (&se, NULL);
- /* For all "simple" expression just get the descriptor or the
- reference, respectively, depending on the rank of the expr. */
- if (code->expr3->rank != 0)
+ /* Convert expr3 to a tree. For all "simple" expression just
+ get the descriptor or the reference, respectively, depending
+ on the rank of the expr. */
+ if (code->ext.alloc.arr_spec_from_expr3 || code->expr3->rank != 0)
gfc_conv_expr_descriptor (&se, code->expr3);
else
gfc_conv_expr_reference (&se, code->expr3);
- if (!code->expr3->mold)
- expr3 = se.expr;
- else
- expr3_tmp = se.expr;
- expr3_len = se.string_length;
- gfc_add_block_to_block (&block, &se.pre);
- gfc_add_block_to_block (&post, &se.post);
+ /* Create a temp variable only for component refs to prevent
+ having to go through the full deref-chain each time and to
+ simplfy computation of array properties. */
+ temp_var_needed = TREE_CODE (se.expr) == COMPONENT_REF;
}
- /* else expr3 = NULL_TREE set above. */
}
else
{
- /* In all other cases evaluate the expr3 and create a
- temporary. */
- gfc_init_se (&se, NULL);
+ /* In all other cases evaluate the expr3. */
symbol_attribute attr;
/* Get the descriptor for all arrays, that are not allocatable or
pointer, because the latter are descriptors already. */
@@ -5205,45 +5200,55 @@ gfc_trans_allocate (gfc_code * code)
code->expr3->ts,
false, true,
false, false);
- gfc_add_block_to_block (&block, &se.pre);
- gfc_add_block_to_block (&post, &se.post);
-
- /* Prevent aliasing, i.e., se.expr may be already a
- variable declaration. */
- if (!VAR_P (se.expr))
+ temp_var_needed = !VAR_P (se.expr);
+ }
+ gfc_add_block_to_block (&block, &se.pre);
+ gfc_add_block_to_block (&post, &se.post);
+ /* Prevent aliasing, i.e., se.expr may be already a
+ variable declaration. */
+ if (se.expr != NULL_TREE && temp_var_needed)
+ {
+ tree var;
+ tmp = GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr)) ?
+ se.expr
+ : build_fold_indirect_ref_loc (input_location, se.expr);
+ /* We need a regular (non-UID) symbol here, therefore give a
+ prefix. */
+ var = gfc_create_var (TREE_TYPE (tmp), "source");
+ if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr)))
{
- tree var;
- tmp = build_fold_indirect_ref_loc (input_location,
- se.expr);
- /* We need a regular (non-UID) symbol here, therefore give a
- prefix. */
- var = gfc_create_var (TREE_TYPE (tmp), "source");
- gfc_add_modify_loc (input_location, &block, var, tmp);
-
- /* Deallocate any allocatable components after all the allocations
- and assignments of expr3 have been completed. */
- if (code->expr3->ts.type == BT_DERIVED
- && code->expr3->rank == 0
- && code->expr3->ts.u.derived->attr.alloc_comp)
- {
- tmp = gfc_deallocate_alloc_comp (code->expr3->ts.u.derived,
- var, 0);
- gfc_add_expr_to_block (&post, tmp);
- }
+ gfc_allocate_lang_decl (var);
+ GFC_DECL_SAVED_DESCRIPTOR (var) = se.expr;
+ }
+ gfc_add_modify_loc (input_location, &block, var, tmp);
- tmp = var;
+ /* Deallocate any allocatable components after all the allocations
+ and assignments of expr3 have been completed. */
+ if (code->expr3->ts.type == BT_DERIVED
+ && code->expr3->rank == 0
+ && code->expr3->ts.u.derived->attr.alloc_comp)
+ {
+ tmp = gfc_deallocate_alloc_comp (code->expr3->ts.u.derived,
+ var, 0);
+ gfc_add_expr_to_block (&post, tmp);
}
- else
- tmp = se.expr;
- if (!code->expr3->mold)
- expr3 = tmp;
- else
- expr3_tmp = tmp;
- /* When he length of a char array is easily available
- here, fix it for future use. */
+
+ expr3 = var;
if (se.string_length)
+ /* Evaluate it assuming that it also is complicated like expr3. */
expr3_len = gfc_evaluate_now (se.string_length, &block);
}
+ else
+ {
+ expr3 = se.expr;
+ expr3_len = se.string_length;
+ }
+ /* Store what the expr3 is to be used for. */
+ e3_is = expr3 != NULL_TREE ?
+ (code->ext.alloc.arr_spec_from_expr3 ?
+ E3_DESC
+ : (code->expr3->mold ? E3_MOLD : E3_SOURCE))
+ : E3_UNSET;
/* Figure how to get the _vtab entry. This also obtains the tree
expression for accessing the _len component, because only
@@ -5258,10 +5263,6 @@ gfc_trans_allocate (gfc_code * code)
if (expr3 != NULL_TREE && GFC_CLASS_TYPE_P (TREE_TYPE (expr3))
&& (VAR_P (expr3) || !code->expr3->ref))
tmp = gfc_class_vptr_get (expr3);
- else if (expr3_tmp != NULL_TREE
- && GFC_CLASS_TYPE_P (TREE_TYPE (expr3_tmp))
- && (VAR_P (expr3_tmp) || !code->expr3->ref))
- tmp = gfc_class_vptr_get (expr3_tmp);
else
{
rhs = gfc_find_and_cut_at_last_class_ref (code->expr3);
@@ -5281,9 +5282,7 @@ gfc_trans_allocate (gfc_code * code)
{
/* Same like for retrieving the _vptr. */
if (expr3 != NULL_TREE && !code->expr3->ref)
- expr3_len = gfc_class_len_get (expr3);
- else if (expr3_tmp != NULL_TREE && !code->expr3->ref)
- expr3_len = gfc_class_len_get (expr3_tmp);
+ expr3_len = gfc_class_len_get (expr3);
else
{
rhs = gfc_find_and_cut_at_last_class_ref (code->expr3);
@@ -5344,8 +5343,11 @@ gfc_trans_allocate (gfc_code * code)
advantage is, that we get scalarizer support for free,
don't have to take care about scalar to array treatment and
will benefit of every enhancements gfc_trans_assignment ()
- gets. */
- if (expr3 != NULL_TREE && DECL_P (expr3) && DECL_ARTIFICIAL (expr3))
+ gets.
+ No need to check whether e3_is is E3_UNSET, because that is
+ done by expr3 != NULL_TREE. */
+ if (e3_is != E3_MOLD && expr3 != NULL_TREE
+ && DECL_P (expr3) && DECL_ARTIFICIAL (expr3))
{
/* Build a temporary symtree and symbol. Do not add it to
the current namespace to prevent accidently modifying
@@ -5397,6 +5399,12 @@ gfc_trans_allocate (gfc_code * code)
}
gcc_assert (expr3_esize);
expr3_esize = fold_convert (sizetype, expr3_esize);
+ if (e3_is == E3_MOLD)
+ {
+ /* The expr3 is no longer valid after this point. */
+ expr3 = NULL_TREE;
+ e3_is = E3_UNSET;
+ }
}
else if (code->ext.alloc.ts.type != BT_UNKNOWN)
{
@@ -5496,7 +5504,11 @@ gfc_trans_allocate (gfc_code * code)
else
tmp = expr3_esize;
if (!gfc_array_allocate (&se, expr, stat, errmsg, errlen,
- label_finish, tmp, &nelems, code->expr3))
+ label_finish, tmp, &nelems,
+ e3rhs ? e3rhs : code->expr3,
+ e3_is == E3_DESC ? expr3 : NULL_TREE,
+ code->expr3 != NULL && e3_is == E3_DESC
+ && code->expr3->expr_type == EXPR_ARRAY))
{
/* A scalar or derived type. First compute the size to
allocate.
@@ -5702,11 +5714,15 @@ gfc_trans_allocate (gfc_code * code)
if (expr3 != NULL_TREE
&& ((POINTER_TYPE_P (TREE_TYPE (expr3))
&& TREE_CODE (expr3) != POINTER_PLUS_EXPR)
- || (VAR_P (expr3) && GFC_CLASS_TYPE_P (TREE_TYPE (expr3))))
+ || (VAR_P (expr3) && GFC_CLASS_TYPE_P (
+ TREE_TYPE (expr3))))
&& code->expr3->ts.type == BT_CLASS
&& (expr->ts.type == BT_CLASS
|| expr->ts.type == BT_DERIVED))
{
+ /* copy_class_to_class can be used for class arrays, too.
+ It just needs to be ensured, that the decl_saved_descriptor
+ has a way to get to the vptr. */
tree to;
to = VAR_P (se.expr) ? se.expr : TREE_OPERAND (se.expr, 0);
tmp = gfc_copy_class_to_class (expr3, to,
@@ -5740,30 +5756,14 @@ gfc_trans_allocate (gfc_code * code)
if (dataref && dataref->u.c.component->as)
{
- int dim;
- gfc_expr *temp;
- gfc_ref *ref = dataref->next;
- ref->u.ar.type = AR_SECTION;
- /* We have to set up the array reference to give ranges
- in all dimensions and ensure that the end and stride
- are set so that the copy can be scalarized. */
- dim = 0;
- for (; dim < dataref->u.c.component->as->rank; dim++)
- {
- ref->u.ar.dimen_type[dim] = DIMEN_RANGE;
- if (ref->u.ar.end[dim] == NULL)
- {
- ref->u.ar.end[dim] = ref->u.ar.start[dim];
- temp = gfc_get_int_expr (gfc_default_integer_kind,
- &al->expr->where, 1);
- ref->u.ar.start[dim] = temp;
- }
- temp = gfc_subtract (gfc_copy_expr (ref->u.ar.end[dim]),
- gfc_copy_expr (ref->u.ar.start[dim]));
- temp = gfc_add (gfc_get_int_expr (gfc_default_integer_kind,
- &al->expr->where, 1),
- temp);
- }
+ gfc_array_spec *as = dataref->u.c.component->as;
+ gfc_free_ref_list (dataref->next);
+ dataref->next = NULL;
+ gfc_add_full_array_ref (last_arg->expr, as);
+ gfc_resolve_expr (last_arg->expr);
+ gcc_assert (last_arg->expr->ts.type == BT_CLASS
+ || last_arg->expr->ts.type == BT_DERIVED);
+ last_arg->expr->ts.type = BT_CLASS;
}
if (rhs->ts.type == BT_CLASS)
{
@@ -5845,7 +5845,7 @@ gfc_trans_allocate (gfc_code * code)
gfc_add_expr_to_block (&block, tmp);
}
else if (code->expr3 && code->expr3->mold
- && code->expr3->ts.type == BT_CLASS)
+ && code->expr3->ts.type == BT_CLASS)
{
/* Since the _vptr has already been assigned to the allocate
object, we can use gfc_copy_class_to_class in its