public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [Patch, Fortran, OOP] PR 64209: runtime segfault with CLASS(*), INTENT(OUT) dummy argument
@ 2014-12-19 12:42 Janus Weil
  2014-12-19 14:27 ` Tobias Burnus
  0 siblings, 1 reply; 4+ messages in thread
From: Janus Weil @ 2014-12-19 12:42 UTC (permalink / raw)
  To: gfortran, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 808 bytes --]

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  <janus@gcc.gnu.org>

    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  <janus@gcc.gnu.org>

    PR fortran/64209
    * gfortran.dg/unlimited_polymorphic_19.f90: New.

[-- Attachment #2: pr64209.diff --]
[-- Type: text/plain, Size: 1807 bytes --]

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

[-- Attachment #3: unlimited_polymorphic_19.f90 --]
[-- Type: text/x-fortran, Size: 1281 bytes --]

! { dg-do run }
!
! PR 64209: [OOP] runtime segfault with CLASS(*), INTENT(OUT) dummy argument
!
! Contributed by Miha Polajnar <polajnar.miha@gmail.com>

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" } }

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Patch, Fortran, OOP] PR 64209: runtime segfault with CLASS(*), INTENT(OUT) dummy argument
  2014-12-19 12:42 [Patch, Fortran, OOP] PR 64209: runtime segfault with CLASS(*), INTENT(OUT) dummy argument Janus Weil
@ 2014-12-19 14:27 ` Tobias Burnus
  2014-12-19 17:28   ` Janus Weil
  0 siblings, 1 reply; 4+ messages in thread
From: Tobias Burnus @ 2014-12-19 14:27 UTC (permalink / raw)
  To: Janus Weil, gcc-patches, fortran

Janus Weil wrote:
> 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?

As you write yourself, the issue can only occur for CLASS(*). Hence,
please apply this only for UNLIMITED_POLY() to avoid unneccessary code side
increase and performance decrease.

OK this this change. Thanks for the patch!

Tobias

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Patch, Fortran, OOP] PR 64209: runtime segfault with CLASS(*), INTENT(OUT) dummy argument
  2014-12-19 14:27 ` Tobias Burnus
@ 2014-12-19 17:28   ` Janus Weil
  2014-12-19 19:34     ` Janus Weil
  0 siblings, 1 reply; 4+ messages in thread
From: Janus Weil @ 2014-12-19 17:28 UTC (permalink / raw)
  To: Tobias Burnus; +Cc: gcc-patches, gfortran

[-- Attachment #1: Type: text/plain, Size: 374 bytes --]

2014-12-19 14:48 GMT+01:00 Tobias Burnus <tobias.burnus@physik.fu-berlin.de>:
> As you write yourself, the issue can only occur for CLASS(*). Hence,
> please apply this only for UNLIMITED_POLY() to avoid unneccessary code side
> increase and performance decrease.

Good point, thanks for reviewing. An updated patch is attached. Will
commit after regtesting.

Cheers,
Janus

[-- Attachment #2: pr64209_v2.diff --]
[-- Type: text/plain, Size: 1586 bytes --]

Index: gcc/fortran/trans-expr.c
===================================================================
--- gcc/fortran/trans-expr.c	(Revision 218957)
+++ gcc/fortran/trans-expr.c	(Arbeitskopie)
@@ -932,6 +932,21 @@ 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);
+
+  if (UNLIMITED_POLY(obj))
+    {
+      /* Check if rhs is non-NULL. */
+      gfc_se src;
+      gfc_init_se (&src, NULL);
+      gfc_conv_expr (&src, rhs);
+      src.expr = gfc_build_addr_expr (NULL_TREE, src.expr);
+      tree 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;
 }
 
@@ -980,6 +995,17 @@ 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);
+
+      if (UNLIMITED_POLY(code->expr1))
+	{
+	  /* Check if _def_init is non-NULL. */
+	  tree 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

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Patch, Fortran, OOP] PR 64209: runtime segfault with CLASS(*), INTENT(OUT) dummy argument
  2014-12-19 17:28   ` Janus Weil
@ 2014-12-19 19:34     ` Janus Weil
  0 siblings, 0 replies; 4+ messages in thread
From: Janus Weil @ 2014-12-19 19:34 UTC (permalink / raw)
  To: Tobias Burnus; +Cc: gcc-patches, gfortran

Committed as r218968.

Cheers,
Janus



2014-12-19 18:24 GMT+01:00 Janus Weil <janus@gcc.gnu.org>:
> 2014-12-19 14:48 GMT+01:00 Tobias Burnus <tobias.burnus@physik.fu-berlin.de>:
>> As you write yourself, the issue can only occur for CLASS(*). Hence,
>> please apply this only for UNLIMITED_POLY() to avoid unneccessary code side
>> increase and performance decrease.
>
> Good point, thanks for reviewing. An updated patch is attached. Will
> commit after regtesting.
>
> Cheers,
> Janus

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2014-12-19 19:31 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-12-19 12:42 [Patch, Fortran, OOP] PR 64209: runtime segfault with CLASS(*), INTENT(OUT) dummy argument Janus Weil
2014-12-19 14:27 ` Tobias Burnus
2014-12-19 17:28   ` Janus Weil
2014-12-19 19:34     ` Janus Weil

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).