This patch corrects errors due to PDT components taking the PDT template as
their type in PDT constructors and component references. The latter took a
long time to debug because yours truly did not catch on to the basic
problem until a light bulb moment, triggered by an excess of coffee :-)
With the benefit of hindsight, it is blindingly obvious and the fix is
straightforward.

Regtests on FC42/x86_64 and behaves as the other brands. OK for mainline?

Regards

Paul

Attachment: Change.Logs
Description: Binary data

diff --git a/gcc/fortran/intrinsic.cc b/gcc/fortran/intrinsic.cc
index e2847f08daa..a422fc176b4 100644
--- a/gcc/fortran/intrinsic.cc
+++ b/gcc/fortran/intrinsic.cc
@@ -5466,6 +5466,9 @@ gfc_convert_type_warn (gfc_expr *expr, gfc_typespec *ts, int eflag, int wflag,
   if (ts->type == BT_UNKNOWN)
     goto bad;
 
+  if (from_ts.type == BT_DERIVED && from_ts.u.derived->attr.pdt_type)
+    *ts = from_ts;
+
   expr->do_not_warn = ! wflag;
 
   /* NULL and zero size arrays get their type here, unless they already have a
diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc
index 6b01b8f7c20..e7c650a7832 100644
--- a/gcc/fortran/resolve.cc
+++ b/gcc/fortran/resolve.cc
@@ -5880,6 +5880,7 @@ gfc_resolve_ref (gfc_expr *expr)
   int current_part_dimension, n_components, seen_part_dimension, dim;
   gfc_ref *ref, **prev, *array_ref;
   bool equal_length;
+  gfc_symbol *last_pdt = NULL;
 
   for (ref = expr->ref; ref; ref = ref->next)
     if (ref->type == REF_ARRAY && ref->u.ar.as == NULL)
@@ -5927,6 +5928,11 @@ gfc_resolve_ref (gfc_expr *expr)
   n_components = 0;
   array_ref = NULL;
 
+  if (expr->expr_type == EXPR_VARIABLE
+      && expr->symtree->n.sym->ts.type == BT_DERIVED
+      && expr->symtree->n.sym->ts.u.derived->attr.pdt_type)
+    last_pdt = expr->symtree->n.sym->ts.u.derived;
+
   for (ref = expr->ref; ref; ref = ref->next)
     {
       switch (ref->type)
@@ -5984,6 +5990,38 @@ gfc_resolve_ref (gfc_expr *expr)
 		}
 	    }
 
+	  /* Sometimes an the component in a component reference is that of the
+	     pdt_template. Point to the component of pdt_type instead. This
+	     ensures that the component gets a backend_decl in translation.  */
+	  if (last_pdt)
+	    {
+	      gfc_component *cmp = last_pdt->components;
+	      for (; cmp; cmp = cmp->next)
+		if (!strcmp (cmp->name, ref->u.c.component->name))
+		  {
+		    ref->u.c.component = cmp;
+		    break;
+		  }
+	      ref->u.c.sym = last_pdt;
+	    }
+
+	  /* Convert pdt_templates, if necessary, and update 'last_pdt'.  */
+	  if (ref->u.c.component->ts.type == BT_DERIVED)
+	    {
+	      if (ref->u.c.component->ts.u.derived->attr.pdt_template)
+		{
+		  if (gfc_get_pdt_instance (ref->u.c.component->param_list,
+					    &ref->u.c.component->ts.u.derived,
+					    NULL) != MATCH_YES)
+		    return false;
+		  last_pdt = ref->u.c.component->ts.u.derived;
+		}
+	      else if (ref->u.c.component->ts.u.derived->attr.pdt_type)
+		last_pdt = ref->u.c.component->ts.u.derived;
+	      else
+		last_pdt = NULL;
+	    }
+
 	  n_components++;
 	  break;
 
diff --git a/gcc/testsuite/gfortran.dg/pdt_40.f03 b/gcc/testsuite/gfortran.dg/pdt_40.f03
new file mode 100644
index 00000000000..48535087f54
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pdt_40.f03
@@ -0,0 +1,25 @@
+! { dg-do run }
+!
+! Contributed by FortranFan at https://groups.google.com/g/comp.lang.fortran/c/NDE6JKTFbNU
+!
+   integer, parameter :: parm = 42
+   type :: t(ell)
+      integer, len :: ell
+      integer :: i
+   end type
+
+   type :: u
+      type(t(ell=:)), allocatable :: x
+   end type
+
+   type(t(ell=:)), allocatable :: foo
+   type(u) :: bar
+
+   allocate( t(ell = parm) :: foo )
+   foo%i = 2 * foo%ell
+
+   bar = u (foo)                    ! Gave: Cannot convert TYPE(Pdtt) to TYPE(t)
+
+   if (bar%x%ell /= parm) stop 1    ! Then these component references failed in
+   if (bar%x%i /= 2 * parm) stop 2  ! translation.
+end

Reply via email to