public inbox for fortran@gcc.gnu.org
 help / color / mirror / Atom feed
* Patch, fortran] PR fortran/100120 - associated intrinsic failure
@ 2021-04-16 16:06 José Rui Faustino de Sousa
  0 siblings, 0 replies; only message in thread
From: José Rui Faustino de Sousa @ 2021-04-16 16:06 UTC (permalink / raw)
  To: fortran, gcc-patches

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

Hi All!

Proposed patch to:

PR100120 - associated intrinsic failure

Patch tested only on x86_64-pc-linux-gnu.

Add code to ensure that pointers have the correct dynamic type.

The patch depends on PR100097 and PR100098.

Thank you very much.

Best regards,
José Rui

Fortran: Fix associated intrinsic failure [PR100120]

gcc/fortran/ChangeLog:

	PR fortran/100120
	* trans-array.c (gfc_conv_expr_descriptor): add code to ensure
	that pointers have the correct dynamic type.

gcc/testsuite/ChangeLog:

	PR fortran/100120
	* gfortran.dg/PR100120.f90: New test.


[-- Attachment #2: PR100120.patch --]
[-- Type: text/x-patch, Size: 6238 bytes --]

diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index ca90142530c..0ef6c788465 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -7598,6 +7598,7 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
       int dim, ndim, codim;
       tree parm;
       tree parmtype;
+      tree dtype;
       tree stride;
       tree from;
       tree to;
@@ -7670,24 +7671,24 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
 	      loop.from[dim] = gfc_index_one_node;
 	    }
 
+      /* The destination must carry the dynamic type of the expression...  */
       desc = info->descriptor;
+      if (expr->ts.type == BT_CHARACTER && expr->ts.deferred)
+	parmtype = gfc_typenode_for_spec (&expr->ts);
+      else
+	parmtype = gfc_get_element_type (TREE_TYPE (desc));
+
+      /* ...But the destination has it's own rank and shape.  */
+      parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen, codim,
+					    loop.from, loop.to, 0,
+					    GFC_ARRAY_UNKNOWN, false);
+
       if (se->direct_byref && !se->byref_noassign)
-	{
-	  /* For pointer assignments we fill in the destination.  */
-	  parm = se->expr;
-	  parmtype = TREE_TYPE (parm);
-	}
+	/* For pointer assignments we fill in the destination.  */
+	parm = se->expr;
       else
 	{
 	  /* Otherwise make a new one.  */
-	  if (expr->ts.type == BT_CHARACTER && expr->ts.deferred)
-	    parmtype = gfc_typenode_for_spec (&expr->ts);
-	  else
-	    parmtype = gfc_get_element_type (TREE_TYPE (desc));
-
-	  parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen, codim,
-						loop.from, loop.to, 0,
-						GFC_ARRAY_UNKNOWN, false);
 	  parm = gfc_create_var (parmtype, "parm");
 
 	  /* When expression is a class object, then add the class' handle to
@@ -7731,8 +7732,18 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
          the offsets because all elements are within the array data.  */
 
       /* Set the dtype.  */
+      if (expr->expr_type == EXPR_VARIABLE
+	  && expr->symtree->n.sym->attr.dummy
+	  && IS_CLASS_ARRAY (expr->symtree->n.sym))
+	{
+	  tmp = gfc_get_class_from_gfc_expr (expr);
+	  tmp = gfc_class_data_get (tmp);
+	  dtype = gfc_conv_descriptor_dtype (tmp);
+	}
+      else
+	dtype = gfc_get_dtype (parmtype);
       tmp = gfc_conv_descriptor_dtype (parm);
-      gfc_add_modify (&loop.pre, tmp, gfc_get_dtype (parmtype));
+      gfc_add_modify (&loop.pre, tmp, dtype);
 
       /* The 1st element in the section.  */
       base = gfc_index_zero_node;
diff --git a/gcc/testsuite/gfortran.dg/PR100120.f90 b/gcc/testsuite/gfortran.dg/PR100120.f90
new file mode 100644
index 00000000000..58a22d72c26
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/PR100120.f90
@@ -0,0 +1,166 @@
+! { dg-do run }
+!
+! Tests fix for PR100120
+!
+
+program main_p
+
+  implicit none
+
+  integer, parameter :: n = 11
+
+  type :: foo_t
+    integer :: i
+  end type foo_t
+
+  type, extends(foo_t) :: bar_t
+    integer :: j(n)
+  end type bar_t
+  
+  class(*),     pointer :: spu
+  class(*),     pointer :: apu(:)
+  class(foo_t), pointer :: spf
+  class(foo_t), pointer :: apf(:)
+  class(bar_t), pointer :: spb
+  class(bar_t), pointer :: apb(:)
+  type(foo_t),   target :: afd(n)
+  type(bar_t),   target :: abd(n)
+  integer,       target :: ain(n)
+  integer               :: i
+
+  ain = [(i, i=1,n)]
+  afd%i = ain
+  abd%i = ain
+  do i = 1, n
+    abd(i)%j = ain
+  end do
+
+  apu => ain
+  if(.not.associated(apu)) stop 1
+  if(.not.associated(apu, ain)) stop 2
+  select type(apu)
+  type is(integer)
+    if(any(apu/=ain)) stop 3
+  class default
+    stop 4
+  end select
+  spu => ain(n)
+  if(.not.associated(spu)) stop 5
+  if(.not.associated(spu, ain(n))) stop 6
+  select type(spu)
+  type is(integer)
+    if(spu/=n) stop 7
+  class default
+    stop 8
+  end select
+
+  apu => afd
+  if(.not.associated(apu)) stop 10
+  if(.not.associated(apu, afd)) stop 11
+  select type(apu)
+  type is(foo_t)
+    if(any(apu%i/=afd%i)) stop 12
+  class default
+    stop 13
+  end select
+  spu => afd(n)
+  if(.not.associated(spu)) stop 14
+  if(.not.associated(spu, afd(n))) stop 15
+  select type(spu)
+  type is(foo_t)
+    if(spu%i/=n) stop 16
+  class default
+    stop 17
+  end select
+  
+  apu => abd
+  if(.not.associated(apu)) stop 20
+  if(.not.associated(apu, abd)) stop 21
+  select type(apu)
+  type is(bar_t)
+    if(any(apu%i/=abd%i)) stop 22
+    do i = 1, n
+      if(any(apu(i)%j/=ain)) stop 23
+    end do
+  class default
+    stop 24
+  end select
+  spu => abd(n)
+  if(.not.associated(spu)) stop 25
+  if(.not.associated(spu, abd(n))) stop 26
+  select type(spu)
+  type is(bar_t)
+    if(spu%i/=n) stop 27
+    if(any(spu%j/=ain)) stop 28
+  class default
+    stop 29
+  end select
+  
+  apf => afd
+  if(.not.associated(apf)) stop 30
+  if(.not.associated(apf, afd)) stop 31
+  select type(apf)
+  type is(foo_t)
+    if(any(apf%i/=afd%i)) stop 32
+  class default
+    stop 33
+  end select
+  spf => afd(n)
+  if(.not.associated(spf)) stop 34
+  if(.not.associated(spf, afd(n))) stop 35
+  select type(spf)
+  type is(foo_t)
+    if(spf%i/=n) stop 36
+  class default
+    stop 37
+  end select
+  
+  apf => abd
+  if(.not.associated(apf)) stop 40
+  if(.not.associated(apf, abd)) stop 41
+  select type(apf)
+  type is(bar_t)
+    if(any(apf%i/=abd%i)) stop 42
+    do i = 1, n
+      if(any(apf(i)%j/=ain)) stop 43
+    end do
+  class default
+    stop 44
+  end select
+  spf => abd(n)
+  if(.not.associated(spf)) stop 45
+  if(.not.associated(spf, abd(n))) stop 46
+  select type(spf)
+  type is(bar_t)
+    if(spf%i/=n) stop 47
+    if(any(spf%j/=ain)) stop 48
+  class default
+    stop 49
+  end select
+  
+  apb => abd
+  if(.not.associated(apb)) stop 50
+  if(.not.associated(apb, abd)) stop 51
+  select type(apb)
+  type is(bar_t)
+    if(any(apb%i/=abd%i)) stop 52
+    do i = 1, n
+      if(any(apb(i)%j/=ain)) stop 53
+    end do
+  class default
+    stop 54
+  end select
+  spb => abd(n)
+  if(.not.associated(spb)) stop 55
+  if(.not.associated(spb, abd(n))) stop 56
+  select type(spb)
+  type is(bar_t)
+    if(spb%i/=n) stop 57
+    if(any(spb%j/=ain)) stop 58
+  class default
+    stop 59
+  end select
+  
+  stop
+
+end program main_p

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-04-16 16:06 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-16 16:06 Patch, fortran] PR fortran/100120 - associated intrinsic failure José Rui Faustino de Sousa

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).