diff mbox

[Fortran,pr78395,v1,OOP] error on polymorphic assignment

Message ID 20161118180017.476fcdaf@vepi2
State New
Headers show

Commit Message

Andre Vehreschild Nov. 18, 2016, 5 p.m. UTC
Hi all,

attached patch fixes the issue which was given by nesting calls to typebound
procedures. The expression of the inner typebound procedure call was resolved
correctly, but in the case of it's having a class type the ref-list was
discarded. Leaving the list of references untouched, resolves the wrong
error-message and generates correct code.

When checking the shortened example in comment #3 one gets a segfault, because
v6 is not allocated explicitly. The initial example made sure, that v6 was
allocated. Reading through the standard, I did not find, whether the
auto-allocation is applicable here. I therefore have extended the testcase by
an allocate(v6). Dominique pointed out, that there are already some prs for
adding an on-demand -fcheck=something runtime check for not allocated objects.
But that does not solve the question, whether v6 should be auto-allocated
when assigned by a typebound-procedure (ifort and cray need v6 allocated do,
i.e., they don't auto-allocate). Btw, when using the in gcc-7 available
polymorphic assign, then v6 is actually auto-allocated and the program runs
fine. So what are your opinions on the auto-allocation issue?

This patch fixes the wrong error messages in both gcc-7 and gcc-6.
Bootstraped and regtested on x86_64-linux/F23 for gcc-7 and -6. Ok for trunk
and gcc-6?

Regards,
	Andre

Comments

Thomas Koenig Nov. 18, 2016, 5:04 p.m. UTC | #1
Hi Andre,


> Btw, when using the in gcc-7 available
> polymorphic assign, then v6 is actually auto-allocated and the program runs
> fine. So what are your opinions on the auto-allocation issue?

It is my experience that such questions can speedily and correctly
be answered by the regulars on comp.lang.fortran.

I have no opinion either way :-)

Regards

	Thomas
Janus Weil Nov. 19, 2016, 3:14 p.m. UTC | #2
Hi Andre,

> When checking the shortened example in comment #3 one gets a segfault, because
> v6 is not allocated explicitly. The initial example made sure, that v6 was
> allocated.

sorry, I guess that's my fault. I blindly removed the allocate
statement when looking for a reduced test case for the compile-time
error.


> Btw, when using the in gcc-7 available
> polymorphic assign, then v6 is actually auto-allocated and the program runs
> fine. So what are your opinions on the auto-allocation issue?

I suspect that auto-allocation does not apply to defined assignment,
but I'm not fully sure. Looking in the F08 standard, it seems to be
mentioned in 7.2.1.3, but not in 7.2.1.4.

As Thomas mentioned, you could take that question to c.l.f. to get a
more qualified answer and/or open a follow-up PR for it.


> This patch fixes the wrong error messages in both gcc-7 and gcc-6.
> Bootstraped and regtested on x86_64-linux/F23 for gcc-7 and -6. Ok for trunk
> and gcc-6?

Yes, looks good to me (at least for trunk; gcc-6 if you like).

Thanks for the patch,
Janus
Andre Vehreschild Nov. 20, 2016, 2:23 p.m. UTC | #3
Hi Janus,

thanks for the review. Committed to trunk as r242637. Will wait one week before
committing to 6.

Regards,
	Andre

On Sat, 19 Nov 2016 16:14:54 +0100
Janus Weil <janus@gcc.gnu.org> wrote:

> Hi Andre,
> 
> > When checking the shortened example in comment #3 one gets a segfault,
> > because v6 is not allocated explicitly. The initial example made sure, that
> > v6 was allocated.  
> 
> sorry, I guess that's my fault. I blindly removed the allocate
> statement when looking for a reduced test case for the compile-time
> error.
> 
> 
> > Btw, when using the in gcc-7 available
> > polymorphic assign, then v6 is actually auto-allocated and the program runs
> > fine. So what are your opinions on the auto-allocation issue?  
> 
> I suspect that auto-allocation does not apply to defined assignment,
> but I'm not fully sure. Looking in the F08 standard, it seems to be
> mentioned in 7.2.1.3, but not in 7.2.1.4.
> 
> As Thomas mentioned, you could take that question to c.l.f. to get a
> more qualified answer and/or open a follow-up PR for it.
> 
> 
> > This patch fixes the wrong error messages in both gcc-7 and gcc-6.
> > Bootstraped and regtested on x86_64-linux/F23 for gcc-7 and -6. Ok for trunk
> > and gcc-6?  
> 
> Yes, looks good to me (at least for trunk; gcc-6 if you like).
> 
> Thanks for the patch,
> Janus
diff mbox

Patch

diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index 825bb12..589a673 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -6140,7 +6140,7 @@  resolve_typebound_function (gfc_expr* e)
 	  gfc_free_ref_list (class_ref->next);
 	  class_ref->next = NULL;
 	}
-      else if (e->ref && !class_ref)
+      else if (e->ref && !class_ref && expr->ts.type != BT_CLASS)
 	{
 	  gfc_free_ref_list (e->ref);
 	  e->ref = NULL;
diff --git a/gcc/testsuite/gfortran.dg/typebound_operator_21.f03 b/gcc/testsuite/gfortran.dg/typebound_operator_21.f03
new file mode 100644
index 0000000..ea374a1
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/typebound_operator_21.f03
@@ -0,0 +1,78 @@ 
+! { dg-do run }
+!
+! Test that pr78395 is fixed.
+! Contributed by Chris and Janus Weil
+
+module types_mod
+  implicit none
+
+  type, public :: t1
+    integer :: a
+  contains
+    procedure :: get_t2
+  end type
+
+  type, public :: t2
+    integer :: b
+  contains
+    procedure, pass(rhs) :: mul2
+    procedure :: assign
+    generic :: operator(*) => mul2
+    generic :: assignment(=) => assign
+  end type
+
+contains
+
+  function get_t2(this)
+    class(t1), intent(in) :: this
+    class(t2), allocatable :: get_t2
+    type(t2), allocatable :: local
+    allocate(local)
+    local%b = this%a
+    call move_alloc(local, get_t2)
+  end function
+
+  function mul2(lhs, rhs)
+    class(t2), intent(in) :: rhs
+    integer, intent(in) :: lhs
+    class(t2), allocatable :: mul2
+    type(t2), allocatable :: local
+    allocate(local)
+    local%b = rhs%b*lhs
+    call move_alloc(local, mul2)
+  end function
+
+  subroutine assign(this, rhs)
+    class(t2), intent(out) :: this
+    class(t2), intent(in)  :: rhs
+    select type(rhs)
+    type is(t2)
+      this%b = rhs%b
+    class default
+      error stop
+    end select
+  end subroutine
+
+end module
+
+
+program minimal
+  use types_mod
+  implicit none
+
+  class(t1), allocatable :: v4
+  class(t2), allocatable :: v6
+
+  allocate(v4, source=t1(4))
+  allocate(v6)
+  v6 = 3 * v4%get_t2() 
+
+  select type (v6)
+    type is (t2)
+      if (v6%b /= 12) error stop
+    class default
+      error stop
+  end select
+  deallocate(v4, v6)
+end
+