Dear maintainers,
The attached patch fixes PR 117303. The reference returned by C_FUNLOC
is assigned to a variable in the added code. Without that,
no reference from the calling subprogram to the argument of C_FUNLOC
was created in the call graph, resulting in an undefined-reference error
with link-time optimization.
The patch was tested using with "check-fortran" on a x86_64-pc-linux-gnu
system. One existing test from gfortran.dg/c_funloc_test_7.f90 failed
as expected due to code-generation change. The generated code was
cfp = (void (*<T6d>) (void)) nocsub;
but now it became
void * D.4685;
D.4685 = (void *) nocsub;
cfp = (void (*<T6f>) (void)) D.4685;
The test has been modified in accordance with the changes.
Another test, gfortran.dg/c_funloc_test_9.f90, has been converted from
the test case in PR.
PR fortran/117303
gcc/fortran/ChangeLog:
* trans-intrinsic.cc (conv_isocbinding_function):
Assign the reference returned by C_FUNLOC to a variable.
gcc/testsuite/ChangeLog:
* gfortran.dg/c_funloc_tests_7.f90:
Updated test due to changed code generation.
* gfortran.dg/c_funloc_tests_9.f90: New test.
Signed-off-by: Kirill Chilikin <[email protected]>
---
Please see the attached file for the actual patch.
If accepted, please commit the change as I do not have write access.
Regards,
KirillFrom 0577f0452d7fd6973dc30f8aa8d8a3091c1560fa Mon Sep 17 00:00:00 2001
From: Kirill Chilikin <[email protected]>
Date: Sun, 25 Jan 2026 14:43:08 +0700
Subject: [PATCH] fortran: Fix creation of reference to C_FUNLOC argument
[PR117303]
The reference returned by C_FUNLOC is assigned to a variable. Without that,
no reference from the calling subprogram to the argument of C_FUNLOC
was created in the call graph, resulting in an undefined-reference error
with link-time optimization. Please see PR 117303 for more details.
PR fortran/117303
gcc/fortran/ChangeLog:
* trans-intrinsic.cc (conv_isocbinding_function):
Assign the reference returned by C_FUNLOC to a variable.
gcc/testsuite/ChangeLog:
* gfortran.dg/c_funloc_tests_7.f90:
Updated test due to changed code generation.
* gfortran.dg/c_funloc_tests_9.f90: New test.
Signed-off-by: Kirill Chilikin <[email protected]>
---
gcc/fortran/trans-intrinsic.cc | 9 ++++-
.../gfortran.dg/c_funloc_tests_7.f90 | 2 +-
.../gfortran.dg/c_funloc_tests_9.f90 | 34 +++++++++++++++++++
3 files changed, 43 insertions(+), 2 deletions(-)
create mode 100644 gcc/testsuite/gfortran.dg/c_funloc_tests_9.f90
diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc
index 722ea933249..cfdd0258241 100644
--- a/gcc/fortran/trans-intrinsic.cc
+++ b/gcc/fortran/trans-intrinsic.cc
@@ -9864,7 +9864,14 @@ conv_isocbinding_function (gfc_se *se, gfc_expr *expr)
se->expr = gfc_evaluate_now (se->expr, &se->pre);
}
else if (expr->value.function.isym->id == GFC_ISYM_C_FUNLOC)
- gfc_conv_expr_reference (se, arg->expr);
+ {
+ gfc_conv_expr_reference (se, arg->expr);
+ /* The code below is necessary to create a reference from the calling
+ subprogram to the argument of C_FUNLOC() in the call graph.
+ Please see PR 117303 for more details. */
+ se->expr = convert (pvoid_type_node, se->expr);
+ se->expr = gfc_evaluate_now (se->expr, &se->pre);
+ }
else if (expr->value.function.isym->id == GFC_ISYM_C_ASSOCIATED)
{
gfc_se arg1se;
diff --git a/gcc/testsuite/gfortran.dg/c_funloc_tests_7.f90 b/gcc/testsuite/gfortran.dg/c_funloc_tests_7.f90
index 7a4464ab552..1e199b4503b 100644
--- a/gcc/testsuite/gfortran.dg/c_funloc_tests_7.f90
+++ b/gcc/testsuite/gfortran.dg/c_funloc_tests_7.f90
@@ -16,6 +16,6 @@ cfp = c_funloc (noCsub)
call c_f_procpointer (cfp, fint)
end
-! { dg-final { scan-tree-dump-times "cfp =\[^;\]+ nocsub;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "D.\[0-9\]* =\[^;\]+ nocsub;" 1 "original" } }
! { dg-final { scan-tree-dump-times "fint =\[^;\]+ cfp;" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/c_funloc_tests_9.f90 b/gcc/testsuite/gfortran.dg/c_funloc_tests_9.f90
new file mode 100644
index 00000000000..2ebb951a6fc
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c_funloc_tests_9.f90
@@ -0,0 +1,34 @@
+! { dg-do link }
+! { dg-options "-O1 -flto" }
+! PR 117303
+
+MODULE M1
+ USE, INTRINSIC :: ISO_C_BINDING
+
+ TYPE T
+ TYPE(C_FUNPTR) FUNPTR
+ END TYPE
+
+ TYPE(T), POINTER :: T_POINTER
+
+CONTAINS
+
+ SUBROUTINE SET_FUNPTR(F)
+ TYPE(C_FUNPTR), INTENT(IN) :: F
+ T_POINTER%FUNPTR = F
+ END SUBROUTINE
+
+ SUBROUTINE S1() BIND(C)
+ END SUBROUTINE
+
+END MODULE
+
+PROGRAM TEST
+ USE M1
+ INTEGER(C_INTPTR_T) I
+ ALLOCATE(T_POINTER)
+ ! There was no reference from TEST to S1 in the call graph,
+ ! resulting in undefined-reference error with link-time optimization.
+ CALL SET_FUNPTR(C_FUNLOC(S1))
+ PRINT *, TRANSFER(T_POINTER%FUNPTR, I)
+END PROGRAM
--
2.39.5