summaryrefslogtreecommitdiffstats
path: root/gcc/fortran/trans-expr.c
diff options
context:
space:
mode:
authorburnus <burnus@138bc75d-0d04-0410-961f-82ee72b054a4>2009-11-01 12:43:42 +0000
committerburnus <burnus@138bc75d-0d04-0410-961f-82ee72b054a4>2009-11-01 12:43:42 +0000
commitd99419eb0cd86223baeb9d06d528cfda2cbcd1b0 (patch)
treea91db28bd70dde1ddc43d774fe7745b81308745a /gcc/fortran/trans-expr.c
parent749ecbf670139a223544beca3160e1ce86d8a440 (diff)
downloadppe42-gcc-d99419eb0cd86223baeb9d06d528cfda2cbcd1b0.tar.gz
ppe42-gcc-d99419eb0cd86223baeb9d06d528cfda2cbcd1b0.zip
2009-11-01 Tobias Burnus <burnus@net-b.de>
PR fortran/41850 * trans-expr.c (gfc_conv_procedure_call): Deallocate intent-out variables only when present. Remove unneccessary present check. 2009-11-01 Tobias Burnus <burnus@net-b.de> PR fortran/41850 * gfortran.dg/intent_out_6.f90: New testcase. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@153793 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fortran/trans-expr.c')
-rw-r--r--gcc/fortran/trans-expr.c42
1 files changed, 29 insertions, 13 deletions
diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index 7eddbd4e28a..8255bb1aea5 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -2935,17 +2935,22 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
gfc_conv_array_parameter (&parmse, e, argss, f, fsym,
sym->name, NULL);
- /* If an ALLOCATABLE dummy argument has INTENT(OUT) and is
- allocated on entry, it must be deallocated. */
- if (fsym && fsym->attr.allocatable
- && fsym->attr.intent == INTENT_OUT)
- {
- tmp = build_fold_indirect_ref_loc (input_location,
- parmse.expr);
- tmp = gfc_trans_dealloc_allocated (tmp);
- gfc_add_expr_to_block (&se->pre, tmp);
- }
-
+ /* If an ALLOCATABLE dummy argument has INTENT(OUT) and is
+ allocated on entry, it must be deallocated. */
+ if (fsym && fsym->attr.allocatable
+ && fsym->attr.intent == INTENT_OUT)
+ {
+ tmp = build_fold_indirect_ref_loc (input_location,
+ parmse.expr);
+ tmp = gfc_trans_dealloc_allocated (tmp);
+ if (fsym->attr.optional
+ && e->expr_type == EXPR_VARIABLE
+ && e->symtree->n.sym->attr.optional)
+ tmp = fold_build3 (COND_EXPR, void_type_node,
+ gfc_conv_expr_present (e->symtree->n.sym),
+ tmp, build_empty_stmt (input_location));
+ gfc_add_expr_to_block (&se->pre, tmp);
+ }
}
}
@@ -2957,9 +2962,20 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
if (e && (fsym == NULL || fsym->attr.optional))
{
/* If an optional argument is itself an optional dummy argument,
- check its presence and substitute a null if absent. */
+ check its presence and substitute a null if absent. This is
+ only needed when passing an array to an elemental procedure
+ as then array elements are accessed - or no NULL pointer is
+ allowed and a "1" or "0" should be passed if not present.
+ When passing a deferred array to a non-deferred array dummy,
+ the array needs to be packed and a check needs thus to be
+ inserted. */
if (e->expr_type == EXPR_VARIABLE
- && e->symtree->n.sym->attr.optional)
+ && e->symtree->n.sym->attr.optional
+ && ((e->rank > 0 && sym->attr.elemental)
+ || e->representation.length || e->ts.type == BT_CHARACTER
+ || (e->rank > 0 && (fsym == NULL
+ || (fsym->as->type != AS_ASSUMED_SHAPE
+ && fsym->as->type != AS_DEFERRED)))))
gfc_conv_missing_dummy (&parmse, e, fsym ? fsym->ts : e->ts,
e->representation.length);
}
OpenPOWER on IntegriCloud