As shown in the PR, updating the function declaration for _gfortran_pack_char could leak into the character typespec back-end declaration to the the caller by setting the backend declaration of the caller.
The problem is that that function returns a character string and in trans-intrinsic.cc, we obtain the function declaration from the call (which may not always work, hmm). In any case, the routine already takes care to of copying the ts->u.cl character length data, i.e. sym->formal[->next etc.]->ts.u.cl but it didn't do so for the result variable, itself, i.e. sym->ts.u.cl. Well, this patch does so – I am just not completely sure what it should do for the character length. In Fortran, the result can either be deferred - or has an explicit length expression (such as 'len(n)'). I now went for 'NULL' instead of copying the length from the caller. For this case, it does not matter as '_s' also has ts->u.cl->length == NULL; Build & regtested on x86-64-gnu-linux. OK? Other thoughts? Tobias PS: The issue is long standing but since a recent GCC 15 commit (cf. PR), the issue is now triggered and causes an ICE for the testcase from the PR.
Fortran: Create fresh ts.u.cl for result in gfc_get_symbol_for_expr [PR118441] For intrinsic routines, called in libraries, the prototype is created from the call via gfc_get_symbol_for_expr. For the actual arguments, it calls gfc_copy_formal_args_intr which already ensures that the ts.u.cl is freshly allocated. This commit now ensures the same for character-returning functions. PR fortran/118441 gcc/fortran/ChangeLog: * trans-intrinsic.cc (gfc_get_symbol_for_expr): Use gfc_new_charlen for character-returning functions. gcc/testsuite/ChangeLog: * gfortran.dg/gomp/intrinsic_pack_7.f90: New test. gcc/fortran/trans-intrinsic.cc | 2 ++ gcc/testsuite/gfortran.dg/gomp/intrinsic_pack_7.f90 | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc index cc3a2e5fc10..afbec5b2752 100644 --- a/gcc/fortran/trans-intrinsic.cc +++ b/gcc/fortran/trans-intrinsic.cc @@ -4242,6 +4242,8 @@ gfc_get_symbol_for_expr (gfc_expr * expr, bool ignore_optional) sym = gfc_new_symbol (expr->value.function.name, NULL); sym->ts = expr->ts; + if (sym->ts.type == BT_CHARACTER) + sym->ts.u.cl = gfc_new_charlen (gfc_current_ns, NULL); sym->attr.external = 1; sym->attr.function = 1; sym->attr.always_explicit = 1; diff --git a/gcc/testsuite/gfortran.dg/gomp/intrinsic_pack_7.f90 b/gcc/testsuite/gfortran.dg/gomp/intrinsic_pack_7.f90 new file mode 100644 index 00000000000..576a8994092 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/intrinsic_pack_7.f90 @@ -0,0 +1,9 @@ +! PR fortran/118441 + +subroutine sub(s) + character(len=*), intent(inout) :: s(:) + integer :: n + s( : ) = s(:) ! OK + n = count(s(:) /= '') + s(1:n) = pack (s(:), mask=(s(:) /= '')) ! ICE +end subroutine sub