Bug 48705 - [OOP] ALLOCATE with non-trivial SOURCE
[OOP] ALLOCATE with non-trivial SOURCE
Status: RESOLVED FIXED
Product: gcc
Classification: Unclassified
Component: fortran
4.7.0
: P3 normal
: ---
Assigned To: Not yet assigned to anyone
: ice-on-valid-code
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2011-04-20 19:34 UTC by Tobias Burnus
Modified: 2012-01-27 10:10 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2011-05-15 13:08:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Tobias Burnus 2011-04-20 19:34:44 UTC
The following program fails with:

generic_deferred_01_pos.f90:45:0: internal compiler error: in fold_convert_loc, at fold-const.c:1915

The test case is part of LRZ's fortran_tests.

module generic_deferred
  implicit none
  type, abstract :: addable
  contains
    private
    procedure(add), deferred :: a
    generic, public :: operator(+) => a 
  end type addable
  abstract interface
    function add(x, y) result(res)
      import :: addable
      class(addable), intent(in) :: x, y
      class(addable), allocatable :: res
    end function add
  end interface
  type, extends(addable) :: vec
    integer :: i(2)
  contains
    procedure :: a => a_vec
  end type
contains
  function a_vec(x, y) result(res)
    class(vec), intent(in) :: x
    class(addable), intent(in) :: y
    class(addable), allocatable :: res
    integer :: ii(2)
    select type(y)
    class is (vec)
      ii = y%i
    end select 
    allocate(vec :: res)
    select type(res)
    type is (vec)
       res%i = x%i + ii
    end select
  end function
end module generic_deferred
program prog
  use generic_deferred
  implicit none
  type(vec) :: x, y
  class(addable), allocatable :: z
!  x = vec( (/1,2/) );   y = vec( (/2,-2/) )
  x%i = (/1,2/); y%i = (/2,-2/)
  allocate(z, source= x + y)
  select type(z)
  type is(vec)
     if (z%i(1) /= 3 .or. z%i(2) /= 0) then
        write(*,*) 'FAIL'
     else
        write(*,*) 'OK'
     end if
  end select
end program prog
Comment 1 janus 2011-05-15 13:08:00 UTC
Reduced test case:


module generic_deferred
  implicit none
  type :: addable
    integer :: i(2)
  contains
    procedure :: add 
  end type
contains
  function add(x, y) result(res)
    class(addable), intent(in) :: x,y
    class(addable), allocatable :: res
    allocate(res)
    res%i = x%i + y%i
  end function
end module

program prog
  use generic_deferred
  implicit none
  type(addable) :: x, y
  class(addable), allocatable :: z
  x = addable((/1,2/))
  y = addable((/2,-2/))
  allocate(z,source=add(x,y))
end program prog


The ICE comes from the ALLOCATE statement.
Comment 2 janus 2011-05-15 17:40:06 UTC
(In reply to comment #1)
>   use generic_deferred
>   implicit none
>   type(addable) :: x, y
>   class(addable), allocatable :: z
>   x = addable((/1,2/))
>   y = addable((/2,-2/))
>   allocate(z,source=add(x,y))
> end program prog
> 
> 
> The ICE comes from the ALLOCATE statement.

I think we'll need to insert a temporary for cases like this, where the SOURCE is not just an EXPR_VARIABLE (cf. gfc_trans_allocate in trans-stmt.c).
Comment 3 Paul Thomas 2012-01-27 10:06:03 UTC
Author: pault
Date: Fri Jan 27 10:05:56 2012
New Revision: 183613

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=183613
Log:
2012-01-27  Paul Thomas  <pault@gcc.gnu.org>
	    Tobias Burnus <burnus@gcc.gnu.org>

	PR fortran/48705
	PR fortran/51870
	PR fortran/51943
	PR fortran/51946
	* trans-array.c (gfc_array_init_size): Add two extra arguments
	to convey the dynamic element size of a calls object and to
	return the number of elements that have been allocated.
	(gfc_array_allocate): Add the same arguments and use them to
	call gfc_array_init_size.  Before the allocation dereference
	the data pointer, if necessary. Set the allocated array to zero
	if the class element size or expr3 are non-null.
	* trans-expr.c (gfc_conv_class_to_class): Give this function
	global scope.
	(get_class_array_ref): New function.
	(gfc_copy_class_to_class): New function.
	* trans-array.h : Update prototype for gfc_array_allocate.
	* trans-stmt.c (gfc_trans_allocate): For non-variable class
	STATUS expressions extract the class object and the dynamic
	element size. Use the latter to call gfc_array_allocate and
	the former for setting the vptr and, via
	gfc_copy_class_to_clasfc_cs, to copy to the allocated data.
	* trans.h : Prototypes for gfc_get_class_array_ref,
	gfc_copy_class_to_class and gfc_conv_class_to_class.
  

2012-01-27  Paul Thomas  <pault@gcc.gnu.org>
	    Tobias Burnus <burnus@gcc.gnu.org>

	PR fortran/48705
	* gfortran.dg/class_allocate_11.f03: New.

	PR fortran/51870
	PR fortran/51943
	PR fortran/51946
	* gfortran.dg/class_allocate_7.f03: New.
	* gfortran.dg/class_allocate_8.f03: New.
	* gfortran.dg/class_allocate_9.f03: New.
	* gfortran.dg/class_allocate_10.f03: New.


Added:
    trunk/gcc/testsuite/gfortran.dg/class_allocate_10.f03
    trunk/gcc/testsuite/gfortran.dg/class_allocate_11.f03
    trunk/gcc/testsuite/gfortran.dg/class_allocate_7.f03
    trunk/gcc/testsuite/gfortran.dg/class_allocate_8.f03
    trunk/gcc/testsuite/gfortran.dg/class_allocate_9.f03
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/trans-array.c
    trunk/gcc/fortran/trans-array.h
    trunk/gcc/fortran/trans-expr.c
    trunk/gcc/fortran/trans-stmt.c
    trunk/gcc/fortran/trans.h
    trunk/gcc/testsuite/ChangeLog
Comment 4 Paul Thomas 2012-01-27 10:10:29 UTC
Fixed on trunk

Thanks for the report

Paul