else
{
+ bool defer_to_dealloc_blk = false;
if (e->ts.type == BT_CLASS && fsym
&& fsym->ts.type == BT_CLASS
&& (!CLASS_DATA (fsym)->as
stmtblock_t block;
tree ptr;
+ defer_to_dealloc_blk = true;
+
gfc_init_block (&block);
ptr = parmse.expr;
if (e->ts.type == BT_CLASS)
&& ((CLASS_DATA (fsym)->as
&& CLASS_DATA (fsym)->as->type == AS_ASSUMED_RANK)
|| CLASS_DATA (e)->attr.dimension))
- gfc_conv_class_to_class (&parmse, e, fsym->ts, false,
+ {
+ gfc_se class_se = parmse;
+ gfc_init_block (&class_se.pre);
+ gfc_init_block (&class_se.post);
+
+ gfc_conv_class_to_class (&class_se, e, fsym->ts, false,
fsym->attr.intent != INTENT_IN
&& (CLASS_DATA (fsym)->attr.class_pointer
|| CLASS_DATA (fsym)->attr.allocatable),
CLASS_DATA (fsym)->attr.class_pointer
|| CLASS_DATA (fsym)->attr.allocatable);
+ parmse.expr = class_se.expr;
+ stmtblock_t *class_pre_block = defer_to_dealloc_blk
+ ? &dealloc_blk
+ : &parmse.pre;
+ gfc_add_block_to_block (class_pre_block, &class_se.pre);
+ gfc_add_block_to_block (&parmse.post, &class_se.post);
+ }
+
if (fsym && (fsym->ts.type == BT_DERIVED
|| fsym->ts.type == BT_ASSUMED)
&& e->ts.type == BT_CLASS
--- /dev/null
+! { dg-do run }
+!
+! PR fortran/92178
+! Check that if a data reference passed is as actual argument whose dummy
+! has INTENT(OUT) attribute, any other argument depending on the
+! same data reference is evaluated before the data reference deallocation.
+
+program p
+ implicit none
+ class(*), allocatable :: c
+ c = 3
+ call bar (allocated(c), c, allocated (c))
+ if (allocated (c)) stop 14
+contains
+ subroutine bar (alloc, x, alloc2)
+ logical :: alloc, alloc2
+ class(*), allocatable, intent(out) :: x(..)
+ if (allocated (x)) stop 5
+ if (.not. alloc) stop 6
+ if (.not. alloc2) stop 16
+ end subroutine bar
+end