[fortran] PR66679 - [OOP] ICE with class(*) and transfer

Message ID CAGkQGiLnxPGo5=6v-8gs3PaYJVnDpJ19Q0GRnb462gkwnyUqOg@mail.gmail.com
State New
Headers show
Series
  • [fortran] PR66679 - [OOP] ICE with class(*) and transfer
Related show

Commit Message

Paul Richard Thomas July 5, 2018, 7:51 a.m.
The comment in the patch says it all.

Bootstrapped and regtested on FC28/x86_64 - OK for trunk?

Paul

2018-07-05  Paul Thomas  <pault@gcc.gnu.org>

    PR fortran/66679
    * trans-intrinsic.c (gfc_conv_intrinsic_transfer): Class array
    elements are returned as references to the data element. Get
    the class expression by stripping back the references. Use this
    for the element size.

2018-07-05  Paul Thomas  <pault@gcc.gnu.org>

    PR fortran/66679
    * gfortran.dg/transfer_class_3.f90: New test.

Comments

Paul Richard Thomas July 23, 2018, 3:51 p.m. | #1
Ping!
On Thu, 5 Jul 2018 at 08:51, Paul Richard Thomas
<paul.richard.thomas@gmail.com> wrote:
>

> The comment in the patch says it all.

>

> Bootstrapped and regtested on FC28/x86_64 - OK for trunk?

>

> Paul

>

> 2018-07-05  Paul Thomas  <pault@gcc.gnu.org>

>

>     PR fortran/66679

>     * trans-intrinsic.c (gfc_conv_intrinsic_transfer): Class array

>     elements are returned as references to the data element. Get

>     the class expression by stripping back the references. Use this

>     for the element size.

>

> 2018-07-05  Paul Thomas  <pault@gcc.gnu.org>

>

>     PR fortran/66679

>     * gfortran.dg/transfer_class_3.f90: New test.




-- 
"If you can't explain it simply, you don't understand it well enough"
- Albert Einstein
Janus Weil July 23, 2018, 8:20 p.m. | #2
Hi Paul,

2018-07-23 17:51 GMT+02:00 Paul Richard Thomas <paul.richard.thomas@gmail.com>:
> Ping!

> On Thu, 5 Jul 2018 at 08:51, Paul Richard Thomas

> <paul.richard.thomas@gmail.com> wrote:

>>

>> The comment in the patch says it all.

>>

>> Bootstrapped and regtested on FC28/x86_64 - OK for trunk?


I don't see anything wrong with the patch, so as far as I'm concerned
it's ok for trunk.

Just one minor style-wise suggestion: I'd move the declaration of the
'class_expr' into the else branch where it's used (in order to have it
as locally as possible).

Thanks for the patch,
Janus



>> 2018-07-05  Paul Thomas  <pault@gcc.gnu.org>

>>

>>     PR fortran/66679

>>     * trans-intrinsic.c (gfc_conv_intrinsic_transfer): Class array

>>     elements are returned as references to the data element. Get

>>     the class expression by stripping back the references. Use this

>>     for the element size.

>>

>> 2018-07-05  Paul Thomas  <pault@gcc.gnu.org>

>>

>>     PR fortran/66679

>>     * gfortran.dg/transfer_class_3.f90: New test.

>

>

>

> --

> "If you can't explain it simply, you don't understand it well enough"

> - Albert Einstein

Patch

Index: gcc/fortran/trans-intrinsic.c
===================================================================
*** gcc/fortran/trans-intrinsic.c	(revision 262299)
--- gcc/fortran/trans-intrinsic.c	(working copy)
*************** gfc_conv_intrinsic_transfer (gfc_se * se
*** 7346,7358 ****
    tree upper;
    tree lower;
    tree stmt;
    gfc_actual_arglist *arg;
    gfc_se argse;
    gfc_array_info *info;
    stmtblock_t block;
    int n;
    bool scalar_mold;
!   gfc_expr *source_expr, *mold_expr;
  
    info = NULL;
    if (se->loop)
--- 7346,7359 ----
    tree upper;
    tree lower;
    tree stmt;
+   tree class_ref = NULL_TREE;
    gfc_actual_arglist *arg;
    gfc_se argse;
    gfc_array_info *info;
    stmtblock_t block;
    int n;
    bool scalar_mold;
!   gfc_expr *source_expr, *mold_expr, *class_expr;
  
    info = NULL;
    if (se->loop)
*************** gfc_conv_intrinsic_transfer (gfc_se * se
*** 7383,7389 ****
      {
        gfc_conv_expr_reference (&argse, arg->expr);
        if (arg->expr->ts.type == BT_CLASS)
! 	source = gfc_class_data_get (argse.expr);
        else
  	source = argse.expr;
  
--- 7384,7407 ----
      {
        gfc_conv_expr_reference (&argse, arg->expr);
        if (arg->expr->ts.type == BT_CLASS)
! 	{
! 	  tmp = build_fold_indirect_ref_loc (input_location, argse.expr);
! 	  if (GFC_CLASS_TYPE_P (TREE_TYPE (tmp)))
! 	    source = gfc_class_data_get (tmp);
! 	  else
! 	    {
! 	      /* Array elements are evaluated as a reference to the data.
! 		 To obtain the vptr for the element size, the argument
! 		 expression must be stripped to the class reference and
! 		 re-evaluated. The pre and post blocks are not needed.  */
! 	      gcc_assert (arg->expr->expr_type == EXPR_VARIABLE);
! 	      source = argse.expr;
! 	      class_expr = gfc_find_and_cut_at_last_class_ref (arg->expr);
! 	      gfc_init_se (&argse, NULL);
! 	      gfc_conv_expr (&argse, class_expr);
! 	      class_ref = argse.expr;
! 	    }
! 	}
        else
  	source = argse.expr;
  
*************** gfc_conv_intrinsic_transfer (gfc_se * se
*** 7395,7400 ****
--- 7413,7421 ----
  					 argse.string_length);
  	  break;
  	case BT_CLASS:
+ 	  if (class_ref != NULL_TREE)
+ 	    tmp = gfc_class_vtab_size_get (class_ref);
+ 	  else
  	    tmp = gfc_class_vtab_size_get (argse.expr);
  	  break;
  	default:
Index: gcc/testsuite/gfortran.dg/transfer_class_3.f90
===================================================================
*** gcc/testsuite/gfortran.dg/transfer_class_3.f90	(nonexistent)
--- gcc/testsuite/gfortran.dg/transfer_class_3.f90	(working copy)
***************
*** 0 ****
--- 1,18 ----
+ ! { dg-do run }
+ !
+ ! Test the fix for PR66679.
+ !
+ ! Contributed by Miha Polajnar  <polajnar.miha@gmail.com>
+ !
+ program main
+   implicit none
+   class(*), allocatable :: vec(:)
+   integer :: var, ans(2)
+   allocate(vec(2),source=[1_4, 2_4])
+ 
+ ! This worked correctly.
+   if (any (transfer(vec,[var],2) .ne. [1_4, 2_4])) stop 1
+ 
+ ! This caused an ICE.
+   if (any ([transfer(vec(1),[var]), transfer(vec(2),[var])] .ne. [1_4, 2_4])) stop 2
+ end program main