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