Hi all,
the attached patch fixes a wrong-code issue with unlimited poylmorphic
INTENT(OUT) arguments.
We default-initialize all polymorphic INTENT(OUT) arguments via the
_def_init component of the vtable. The problem is that the intrinsic
types don't have a default initialization. Therefore their _def_init
is NULL and we simply failed to check for that condition. That's what
the patch does. It regtests cleanly on x86_64-unknown-linux-gnu.
Ok for trunk?
Cheers,
Janus
2014-12-19 Janus Weil <[email protected]>
PR fortran/64209
* trans-expr.c (gfc_trans_class_array_init_assign): Check if _def_init
component is non-NULL.
(gfc_trans_class_init_assign): Ditto.
2014-12-19 Janus Weil <[email protected]>
PR fortran/64209
* gfortran.dg/unlimited_polymorphic_19.f90: New.
Index: gcc/fortran/trans-expr.c
===================================================================
--- gcc/fortran/trans-expr.c (Revision 218896)
+++ gcc/fortran/trans-expr.c (Arbeitskopie)
@@ -912,7 +912,8 @@ gfc_trans_class_array_init_assign (gfc_expr *rhs,
gfc_actual_arglist *actual;
gfc_expr *ppc;
gfc_code *ppc_code;
- tree res;
+ tree res, cond;
+ gfc_se src;
actual = gfc_get_actual_arglist ();
actual->expr = gfc_copy_expr (rhs);
@@ -932,6 +933,16 @@ gfc_trans_class_array_init_assign (gfc_expr *rhs,
of arrays in gfc_trans_call. */
res = gfc_trans_call (ppc_code, false, NULL, NULL, false);
gfc_free_statements (ppc_code);
+
+ gfc_init_se (&src, NULL);
+ gfc_conv_expr (&src, rhs);
+ src.expr = gfc_build_addr_expr (NULL_TREE, src.expr);
+ cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
+ src.expr, fold_convert (TREE_TYPE (src.expr),
+ null_pointer_node));
+ res = build3_loc (input_location, COND_EXPR, TREE_TYPE (res), cond, res,
+ build_empty_stmt (input_location));
+
return res;
}
@@ -943,7 +954,7 @@ tree
gfc_trans_class_init_assign (gfc_code *code)
{
stmtblock_t block;
- tree tmp;
+ tree tmp, cond;
gfc_se dst,src,memsz;
gfc_expr *lhs, *rhs, *sz;
@@ -980,6 +991,12 @@ gfc_trans_class_init_assign (gfc_code *code)
src.expr = gfc_build_addr_expr (NULL_TREE, src.expr);
tmp = gfc_build_memcpy_call (dst.expr, src.expr, memsz.expr);
+
+ cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
+ src.expr, fold_convert (TREE_TYPE (src.expr),
+ null_pointer_node));
+ tmp = build3_loc (input_location, COND_EXPR, TREE_TYPE (tmp), cond, tmp,
+ build_empty_stmt (input_location));
}
if (code->expr1->symtree->n.sym->attr.optional
! { dg-do run }
!
! PR 64209: [OOP] runtime segfault with CLASS(*), INTENT(OUT) dummy argument
!
! Contributed by Miha Polajnar <[email protected]>
MODULE m
IMPLICIT NONE
TYPE :: t
CLASS(*), ALLOCATABLE :: x(:)
CONTAINS
PROCEDURE :: copy
END TYPE t
INTERFACE
PURE SUBROUTINE copy_proc_intr(a,b)
CLASS(*), INTENT(IN) :: a
CLASS(*), INTENT(OUT) :: b
END SUBROUTINE copy_proc_intr
END INTERFACE
CONTAINS
SUBROUTINE copy(self,cp,a)
CLASS(t), INTENT(IN) :: self
PROCEDURE(copy_proc_intr) :: cp
CLASS(*), INTENT(OUT) :: a(:)
INTEGER :: i
IF( .not.same_type_as(self%x(1),a(1)) ) STOP -1
DO i = 1, size(self%x)
CALL cp(self%x(i),a(i))
END DO
END SUBROUTINE copy
END MODULE m
PROGRAM main
USE m
IMPLICIT NONE
INTEGER, PARAMETER :: n = 3, x(n) = [ 1, 2, 3 ]
INTEGER :: copy_x(n)
TYPE(t) :: test
ALLOCATE(test%x(n),SOURCE=x)
CALL test%copy(copy_int,copy_x)
! PRINT '(*(I0,:2X))', copy_x
CONTAINS
PURE SUBROUTINE copy_int(a,b)
CLASS(*), INTENT(IN) :: a
CLASS(*), INTENT(OUT) :: b
SELECT TYPE(a); TYPE IS(integer)
SELECT TYPE(b); TYPE IS(integer)
b = a
END SELECT; END SELECT
END SUBROUTINE copy_int
END PROGRAM main
! { dg-final { cleanup-modules "m" } }