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