]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
fortran: Fix creation of reference to C_FUNLOC argument [PR117303]
authorKirill Chilikin <chilikin.k@gmail.com>
Sun, 25 Jan 2026 07:43:08 +0000 (14:43 +0700)
committerHarald Anlauf <anlauf@gmx.de>
Tue, 3 Feb 2026 20:05:48 +0000 (21:05 +0100)
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 <chilikin.k@gmail.com>
gcc/fortran/trans-intrinsic.cc
gcc/testsuite/gfortran.dg/c_funloc_tests_7.f90
gcc/testsuite/gfortran.dg/c_funloc_tests_9.f90 [new file with mode: 0644]

index 722ea933249232f762e5ec4422937bd0405760df..cfdd0258241a4b212f3ec3f6c8dd92927ef8e9c7 100644 (file)
@@ -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;
index 7a4464ab552898d8d114ea4e38a6d50b9d58ae1c..1e199b4503be75314e3f71fc70f722c0f96b22fd 100644 (file)
@@ -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 (file)
index 0000000..2ebb951
--- /dev/null
@@ -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