aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran
diff options
context:
space:
mode:
authorPaul Thomas <pault@gcc.gnu.org>2011-02-06 14:22:48 +0000
committerPaul Thomas <pault@gcc.gnu.org>2011-02-06 14:22:48 +0000
commit90cf3ecc837d6f0c8d7b9068d9321bf494a830c6 (patch)
tree83ccb035c9e45ef14dd291bdc88ba6dea11e5cf6 /gcc/fortran
parentd5d3781a0d0934ad401412cd5471adc8519e463d (diff)
downloadgcc-90cf3ecc837d6f0c8d7b9068d9321bf494a830c6.zip
gcc-90cf3ecc837d6f0c8d7b9068d9321bf494a830c6.tar.gz
gcc-90cf3ecc837d6f0c8d7b9068d9321bf494a830c6.tar.bz2
re PR fortran/47592 (Multiple function invocation with ALLOCATE (SOURCE=REPEAT('x',bar())))
2011-02-06 Paul Thomas <pault@gcc.gnu.org> PR fortran/47592 * trans-stmt.c (gfc_trans_allocate): For deferred character length allocations with SOURCE, store to the values and string length to avoid calculating twice. Replace gfc_start_block with gfc_init_block to avoid unnecessary contexts and to keep declarations of temporaries where they should be. Tidy up the code a bit. 2011-02-06 Paul Thomas <pault@gcc.gnu.org> PR fortran/47592 * gfortran.dg/allocate_with_source_1 : New test. From-SVN: r169862
Diffstat (limited to 'gcc/fortran')
-rw-r--r--gcc/fortran/ChangeLog10
-rw-r--r--gcc/fortran/trans-stmt.c87
2 files changed, 52 insertions, 45 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index b936715..7fc66e0 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,13 @@
+2011-02-06 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/47592
+ * trans-stmt.c (gfc_trans_allocate): For deferred character
+ length allocations with SOURCE, store to the values and string
+ length to avoid calculating twice. Replace gfc_start_block
+ with gfc_init_block to avoid unnecessary contexts and to keep
+ declarations of temporaries where they should be. Tidy up the
+ code a bit.
+
2011-02-05 Janne Blomqvist <jb@gcc.gnu.org>
PR fortran/42434
diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c
index 2ac6989..6ddb2ca 100644
--- a/gcc/fortran/trans-stmt.c
+++ b/gcc/fortran/trans-stmt.c
@@ -4451,14 +4451,20 @@ gfc_trans_allocate (gfc_code * code)
tree pstat;
tree error_label;
tree memsz;
+ tree expr3;
+ tree slen3;
stmtblock_t block;
+ stmtblock_t post;
+ gfc_expr *sz;
+ gfc_se se_sz;
if (!code->ext.alloc.list)
return NULL_TREE;
pstat = stat = error_label = tmp = memsz = NULL_TREE;
- gfc_start_block (&block);
+ gfc_init_block (&block);
+ gfc_init_block (&post);
/* Either STAT= and/or ERRMSG is present. */
if (code->expr1 || code->expr2)
@@ -4472,6 +4478,9 @@ gfc_trans_allocate (gfc_code * code)
TREE_USED (error_label) = 1;
}
+ expr3 = NULL_TREE;
+ slen3 = NULL_TREE;
+
for (al = code->ext.alloc.list; al != NULL; al = al->next)
{
expr = gfc_copy_expr (al->expr);
@@ -4480,7 +4489,6 @@ gfc_trans_allocate (gfc_code * code)
gfc_add_data_component (expr);
gfc_init_se (&se, NULL);
- gfc_start_block (&se.pre);
se.want_pointer = 1;
se.descriptor_only = 1;
@@ -4495,8 +4503,6 @@ gfc_trans_allocate (gfc_code * code)
{
if (code->expr3->ts.type == BT_CLASS)
{
- gfc_expr *sz;
- gfc_se se_sz;
sz = gfc_copy_expr (code->expr3);
gfc_add_vptr_component (sz);
gfc_add_size_component (sz);
@@ -4514,7 +4520,6 @@ gfc_trans_allocate (gfc_code * code)
if (!code->expr3->ts.u.cl->backend_decl)
{
/* Convert and use the length expression. */
- gfc_se se_sz;
gfc_init_se (&se_sz, NULL);
if (code->expr3->expr_type == EXPR_VARIABLE
|| code->expr3->expr_type == EXPR_CONSTANT)
@@ -4522,7 +4527,8 @@ gfc_trans_allocate (gfc_code * code)
gfc_conv_expr (&se_sz, code->expr3);
memsz = se_sz.string_length;
}
- else if (code->expr3->ts.u.cl
+ else if (code->expr3->mold
+ && code->expr3->ts.u.cl
&& code->expr3->ts.u.cl->length)
{
gfc_conv_expr (&se_sz, code->expr3->ts.u.cl->length);
@@ -4531,20 +4537,21 @@ gfc_trans_allocate (gfc_code * code)
gfc_add_block_to_block (&se.pre, &se_sz.post);
memsz = se_sz.expr;
}
- else if (code->ext.alloc.ts.u.cl
- && code->ext.alloc.ts.u.cl->length)
- {
- gfc_conv_expr (&se_sz, code->ext.alloc.ts.u.cl->length);
- memsz = se_sz.expr;
- }
else
{
- /* This is likely to be inefficient. */
- gfc_conv_expr (&se_sz, code->expr3);
- gfc_add_block_to_block (&se.pre, &se_sz.pre);
- se_sz.expr = gfc_evaluate_now (se_sz.expr, &se.pre);
- gfc_add_block_to_block (&se.pre, &se_sz.post);
- memsz = se_sz.string_length;
+ /* This is would be inefficient and possibly could
+ generate wrong code if the result were not stored
+ in expr3/slen3. */
+ if (slen3 == NULL_TREE)
+ {
+ gfc_conv_expr (&se_sz, code->expr3);
+ gfc_add_block_to_block (&se.pre, &se_sz.pre);
+ expr3 = gfc_evaluate_now (se_sz.expr, &se.pre);
+ gfc_add_block_to_block (&post, &se_sz.post);
+ slen3 = gfc_evaluate_now (se_sz.string_length,
+ &se.pre);
+ }
+ memsz = slen3;
}
}
else
@@ -4580,31 +4587,13 @@ gfc_trans_allocate (gfc_code * code)
TREE_TYPE (tmp), tmp,
fold_convert (TREE_TYPE (tmp), memsz));
}
+
/* Allocate - for non-pointers with re-alloc checking. */
- {
- gfc_ref *ref;
- bool allocatable;
-
- ref = expr->ref;
-
- /* Find the last reference in the chain. */
- while (ref && ref->next != NULL)
- {
- gcc_assert (ref->type != REF_ARRAY || ref->u.ar.type == AR_ELEMENT);
- ref = ref->next;
- }
-
- if (!ref)
- allocatable = expr->symtree->n.sym->attr.allocatable;
- else
- allocatable = ref->u.c.component->attr.allocatable;
-
- if (allocatable)
- tmp = gfc_allocate_array_with_status (&se.pre, se.expr, memsz,
- pstat, expr);
- else
- tmp = gfc_allocate_with_status (&se.pre, memsz, pstat);
- }
+ if (gfc_expr_attr (expr).allocatable)
+ tmp = gfc_allocate_array_with_status (&se.pre, se.expr, memsz,
+ pstat, expr);
+ else
+ tmp = gfc_allocate_with_status (&se.pre, memsz, pstat);
tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
se.expr,
@@ -4629,11 +4618,9 @@ gfc_trans_allocate (gfc_code * code)
tmp = gfc_nullify_alloc_comp (expr->ts.u.derived, tmp, 0);
gfc_add_expr_to_block (&se.pre, tmp);
}
-
}
- tmp = gfc_finish_block (&se.pre);
- gfc_add_expr_to_block (&block, tmp);
+ gfc_add_block_to_block (&block, &se.pre);
if (code->expr3 && !code->expr3->mold)
{
@@ -4668,6 +4655,13 @@ gfc_trans_allocate (gfc_code * code)
gfc_add_block_to_block (&call.pre, &call.post);
tmp = gfc_finish_block (&call.pre);
}
+ else if (expr3 != NULL_TREE)
+ {
+ tmp = build_fold_indirect_ref_loc (input_location, se.expr);
+ gfc_trans_string_copy (&block, slen3, tmp, code->expr3->ts.kind,
+ slen3, expr3, code->expr3->ts.kind);
+ tmp = NULL_TREE;
+ }
else
{
/* Switch off automatic reallocation since we have just done
@@ -4799,6 +4793,9 @@ gfc_trans_allocate (gfc_code * code)
gfc_add_expr_to_block (&block, tmp);
}
+ gfc_add_block_to_block (&block, &se.post);
+ gfc_add_block_to_block (&block, &post);
+
return gfc_finish_block (&block);
}