Re: [PATCH v2] fortran: refresh associate-name kind once selector is resolved [PR125172] When the ASSOCIATE target is a forward reference to an internal or contained function whose return type is not yet known at parse time, primary.cc infers a type for the associate-name from a %re/%im/%len inquiry using the default kind (e.g. complex(4) when the user wrote k%re). The actual selector kind cannot be known at that point. The inferred-type cleanup in resolve_assoc_var only refreshed the typespec when the target was BT_DERIVED/BT_CLASS, so for an inferred intrinsic complex/character associate-name sym->ts kept the default kind. Resolved expressions referencing the associate-name (or applying the %re/%im inquiry) inherited that wrong kind, so for a function returning complex(real64) one would see kind(k%re) == 4. Refresh the kind in three places once the selector's actu
Jonathan Wakely <[email protected]>
| Newsgroups | gmane.comp.gcc.patches,gmane.comp.gcc.fortran |
|---|---|
| Message-ID | <[email protected]> |
On Wed, 06 May 2026 at 20:06 +0200, Samir Ouchene wrote: >Signed-off-by: Samir Ouchene <[email protected]> >v2: resending; v1 was sent through a webmail client and the commit > message body collapsed into the Subject header. The diff is > unchanged. v2 has the same problem: https://gcc.gnu.org/pipermail/gcc-patches/2026-May/715964.html >Hi, >The fortran list confirmed this as PR fortran/125172. Tested on >x86_64-pc-linux-gnu (Ubuntu 24.04, WSL2) against current trunk; the >new gfortran.dg/associate_79.f90 fails on unpatched trunk and passes >after the fix. No new gfortran.dg regressions observed. >I do not have commit access; could a maintainer push this when >reviewed? >Thanks, >Samir >--- > gcc/fortran/resolve.cc | 26 +++++++++++++++++ > gcc/testsuite/gfortran.dg/associate_79.f90 | 34 ++++++++++++++++++++++ > 2 files changed, 60 insertions(+) > create mode 100644 gcc/testsuite/gfortran.dg/associate_79.f90 > >diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc >index a5d9add9d..0db362758 100644 >--- a/gcc/fortran/resolve.cc >+++ b/gcc/fortran/resolve.cc >@@ -6578,6 +6578,13 @@ resolve_variable (gfc_expr *e) > if (e->expr_type == EXPR_CONSTANT) > return true; > } >+ else if (IS_INFERRED_TYPE (e) >+ && sym->ts.type != BT_UNKNOWN >+ && (sym->ts.type != e->ts.type || sym->ts.kind != e->ts.kind)) >+ /* No subobject ref, but the expression's typespec was set at parse >+ time before the target's actual type/kind was known. Refresh from >+ the now-resolved associate-name symbol. */ >+ e->ts = sym->ts; > else if (sym->attr.select_type_temporary > && sym->ns->assoc_name_inferred) > gfc_fixup_inferred_type_refs (e); >@@ -6962,6 +6969,15 @@ gfc_fixup_inferred_type_refs (gfc_expr *e) > sym->assoc->target->ts.kind); > gfc_replace_expr (e, ne); > } >+ else if (ref && ref->type == REF_INQUIRY >+ && (ref->u.i == INQUIRY_RE || ref->u.i == INQUIRY_IM) >+ && sym->ts.type == BT_COMPLEX >+ && e->ts.type == BT_REAL >+ && e->ts.kind != sym->ts.kind) >+ /* primary.cc set the inquiry-result kind to the default real kind >+ when the associate-name's type was inferred from %re/%im before >+ the target was resolved. Now use the (resolved) selector kind. */ >+ e->ts.kind = sym->ts.kind; > > /* Now that the references are all sorted out, set the expression rank > and return. */ >@@ -10680,6 +10696,16 @@ resolve_assoc_var (gfc_symbol* sym, bool resolve_target) > /* Confirmed to be either a derived type or misidentified to be a > scalar class object, when the selector is a class array. */ > sym->ts = target->ts; >+ else if (sym->assoc->inferred_type >+ && (sym->ts.type == BT_COMPLEX >+ || sym->ts.type == BT_CHARACTER) >+ && target->ts.type == sym->ts.type >+ && sym->ts.kind != target->ts.kind) >+ /* The inferred type was set from a %re, %im or %len inquiry on >+ the associate name with the default kind, before the target's >+ actual type was known. Now that the target has been resolved, >+ update the kind to match. */ >+ sym->ts = target->ts; > } > > >diff --git a/gcc/testsuite/gfortran.dg/associate_79.f90 b/gcc/testsuite/gfortran.dg/associate_79.f90 >new file mode 100644 >index 000000000..c7b04e0ab >--- /dev/null >+++ b/gcc/testsuite/gfortran.dg/associate_79.f90 >@@ -0,0 +1,34 @@ >+! { dg-do run } >+! >+! Verify that an associate-name whose target is a call to an internal >+! procedure (CONTAINS in a program) gets the correct declared kind from >+! the function's return type, instead of falling back to default kind. >+! >+program demo >+ use, intrinsic :: iso_fortran_env, only: wp => real64 >+ implicit none >+ complex(wp) :: z >+ real(wp) :: re_ref, im_ref >+ >+ z = (1.0_wp, 2.0_wp) >+ re_ref = real (sin (z), wp) >+ im_ref = aimag (sin (z)) >+ >+ associate (k => myfunc (z)) >+ if (kind (k%re) /= kind (1.0_wp)) stop 1 >+ if (kind (k%im) /= kind (1.0_wp)) stop 2 >+ if (kind (aimag (k)) /= kind (1.0_wp)) stop 3 >+ if (abs (k%re - re_ref) > 1.0e-12_wp) stop 4 >+ if (abs (k%im - im_ref) > 1.0e-12_wp) stop 5 >+ if (abs (aimag (k) - im_ref) > 1.0e-12_wp) stop 6 >+ end associate >+ >+contains >+ >+ complex(wp) function myfunc (x) >+ complex(wp), intent(in) :: x >+ myfunc = sin (x) >+ end function myfunc >+ >+end program demo >+ >-- >2.54.0 > >