Subject: bug#78464: Guile fails to build with GCC 15

From: Collin Funk <[email-masked]>
Date: Fri, 16 May 2025 23:12:27 -0700

GCC 15 defaults to '-std=gnu23' which leads to Guile failing to build
after running './configure && make'. This is because C23 made:

    int foo ();

equal to:

   int foo (void);

Unlike previous C standards where it was just a function with
unspecified arguments.

I have attached a patch that fixes this.

Collin

>From ea57c7f79f92e2be7a179464ae7f45e1e130a075 Mon Sep 17 00:00:00 2001
From: Collin Funk <[email-masked]>
Date: Fri, 16 May 2025 22:51:57 -0700
Subject: [PATCH] Fix build with C23 compilers.

* libguile/scm.h (scm_t_subr): Always define to void pointer.  Update
commentary to account for C23.
* libguile/lightening/lightening.h (jit_function_pointer_t): Define to a
void pointer.
* libguile/init.c (scm_boot_guile): Add prototype to main_func.
* libguile/hash.c (floor): Add function prototype.
* libguile/posix.c (scm_getpgrp): Just call the system definition
directly.
* libguile/array-map.c (scm_ramapc): Cast the function pointer with the
correct number of arguments.
* libguile/gsubr.c (scm_apply_subr): Likewise.
(scm_c_make_gsubr, scm_c_define_gsubr, scm_c_make_gsubr_with_generic)
scm_c_define_gsubr_with_generic): Use scm_t_subr for the fcn argument
which matches the declarations in libguile/gsubr.h.
* libguile/fluids.c (scm_c_with_fluids, scm_with_fluid): Add function
prototype to cproc.
* libguile/smob.c (apply_0, apply_1, apply_2, apply_3): Cast the
function with the correct number of arguments.
(scm_set_smob_apply): Use scm_t_subr for the apply argument which
patches libguile/smob.h.
---
 libguile/array-map.c             |  5 ++--
 libguile/fluids.c                |  4 +--
 libguile/gsubr.c                 | 51 +++++++++++++++++++-------------
 libguile/hash.c                  |  2 +-
 libguile/init.c                  |  3 +-
 libguile/lightening/lightening.h |  2 +-
 libguile/posix.c                 |  4 +--
 libguile/scm.h                   | 10 ++-----
 libguile/smob.c                  | 10 +++----
 9 files changed, 47 insertions(+), 44 deletions(-)

diff --git a/libguile/array-map.c b/libguile/array-map.c
index ce0f7ba09..db0efd791 100644
--- a/libguile/array-map.c
+++ b/libguile/array-map.c
@@ -101,7 +101,6 @@ cindk (SCM ra, ssize_t *ve, int kend)
 int
 scm_ramapc (void *cproc_ptr, SCM data, SCM ra0, SCM lra, const char *what)
 {
-  int (*cproc) () = cproc_ptr;
   SCM z, va0, lva, *plva;
   int k, kmax, kroll;
   ssize_t *vi, inc;
@@ -197,7 +196,9 @@ scm_ramapc (void *cproc_ptr, SCM data, SCM ra0, SCM lra, const char *what)
           SCM_I_ARRAY_SET_BASE (va0, cindk (ra0, vi, kroll));
           for (z = lva; !scm_is_null (z); z = SCM_CDR (z), y = SCM_CDR (y))
             SCM_I_ARRAY_SET_BASE (SCM_CAR (z), cindk (SCM_CAR (y), vi, kroll));
-          if (! (SCM_UNBNDP (data) ? cproc (va0, lva) : cproc (va0, data, lva)))
+          if (! (SCM_UNBNDP (data)
+                 ? ((int (*) (SCM, SCM)) cproc_ptr) (va0, lva)
+                 : ((int (*) (SCM, SCM, SCM)) cproc_ptr) (va0, data, lva)))
             return 0;
           --k;
         }
diff --git a/libguile/fluids.c b/libguile/fluids.c
index ebdb48fbc..f6d918a34 100644
--- a/libguile/fluids.c
+++ b/libguile/fluids.c
@@ -506,7 +506,7 @@ SCM_DEFINE (scm_with_fluids, "with-fluids*", 3, 0, 0,
 #undef FUNC_NAME
 
 SCM
-scm_c_with_fluids (SCM fluids, SCM values, SCM (*cproc) (), void *cdata)
+scm_c_with_fluids (SCM fluids, SCM values, SCM (*cproc) (void *), void *cdata)
 #define FUNC_NAME "scm_c_with_fluids"
 {
   SCM ans;
@@ -544,7 +544,7 @@ scm_with_fluid (SCM fluid, SCM value, SCM thunk)
 }
 
 SCM
-scm_c_with_fluid (SCM fluid, SCM value, SCM (*cproc) (), void *cdata)
+scm_c_with_fluid (SCM fluid, SCM value, SCM (*cproc) (void *), void *cdata)
 #define FUNC_NAME "scm_c_with_fluid"
 {
   SCM ans;
diff --git a/libguile/gsubr.c b/libguile/gsubr.c
index a33cbb9c4..c3afd6f47 100644
--- a/libguile/gsubr.c
+++ b/libguile/gsubr.c
@@ -467,38 +467,47 @@ scm_subr_name (SCM subr)
 SCM
 scm_apply_subr (union scm_vm_stack_element *sp, uint32_t idx, ptrdiff_t nslots)
 {
-  SCM (*subr)() = subrs[idx];
+  void *subr = subrs[idx];
 
 #define ARG(i) (sp[i].as_scm)
   switch (nslots - 1)
     {
     case 0:
-      return subr ();
+      return ((SCM (*) (void)) subr) ();
     case 1:
-      return subr (ARG (0));
+      return ((SCM (*) (SCM)) subr) (ARG (0));
     case 2:
-      return subr (ARG (1), ARG (0));
+      return ((SCM (*) (SCM, SCM)) subr) (ARG (1), ARG (0));
     case 3:
-      return subr (ARG (2), ARG (1), ARG (0));
+      return ((SCM (*) (SCM, SCM, SCM)) subr) (ARG (2), ARG (1), ARG (0));
     case 4:
-      return subr (ARG (3), ARG (2), ARG (1), ARG (0));
+      return ((SCM (*) (SCM, SCM, SCM, SCM)) subr) (ARG (3), ARG (2), ARG (1),
+                                                    ARG (0));
     case 5:
-      return subr (ARG (4), ARG (3), ARG (2), ARG (1), ARG (0));
+      return ((SCM (*) (SCM, SCM, SCM, SCM, SCM)) subr) (ARG (4), ARG (3),
+                                                         ARG (2), ARG (1),
+                                                         ARG (0));
     case 6:
-      return subr (ARG (5), ARG (4), ARG (3), ARG (2), ARG (1),
-                   ARG (0));
+      return ((SCM (*) (SCM, SCM, SCM, SCM, SCM, SCM)) subr) (ARG (5), ARG (4),
+                                                              ARG (3), ARG (2),
+                                                              ARG (1),
+                                                              ARG (0));
     case 7:
-      return subr (ARG (6), ARG (5), ARG (4), ARG (3), ARG (2),
-                   ARG (1), ARG (0));
+      return ((SCM (*) (SCM, SCM, SCM, SCM, SCM, SCM, SCM)) subr)
+        (ARG (6), ARG (5), ARG (4), ARG (3), ARG (2), ARG (1), ARG (0));
     case 8:
-      return subr (ARG (7), ARG (6), ARG (5), ARG (4), ARG (3),
-                   ARG (2), ARG (1), ARG (0));
+      return ((SCM (*) (SCM, SCM, SCM, SCM, SCM, SCM, SCM, SCM)) subr)
+        (ARG (7), ARG (6), ARG (5), ARG (4), ARG (3), ARG (2), ARG (1),
+         ARG (0));
     case 9:
-      return subr (ARG (8), ARG (7), ARG (6), ARG (5), ARG (4),
-                   ARG (3), ARG (2), ARG (1), ARG (0));
+      return ((SCM (*) (SCM, SCM, SCM, SCM, SCM, SCM, SCM, SCM, SCM)) subr)
+        (ARG (8), ARG (7), ARG (6), ARG (5), ARG (4), ARG (3), ARG (2),
+         ARG (1), ARG (0));
     case 10:
-      return subr (ARG (9), ARG (8), ARG (7), ARG (6), ARG (5),
-                   ARG (4), ARG (3), ARG (2), ARG (1), ARG (0));
+      return
+        ((SCM (*) (SCM, SCM, SCM, SCM, SCM, SCM, SCM, SCM, SCM, SCM)) subr)
+          (ARG (9), ARG (8), ARG (7), ARG (6), ARG (5), ARG (4), ARG (3),
+           ARG (2), ARG (1), ARG (0));
     default:
       abort (); /* SCM_GSUBR_MAX */
     }
@@ -506,13 +515,13 @@ scm_apply_subr (union scm_vm_stack_element *sp, uint32_t idx, ptrdiff_t nslots)
 }
 
 SCM
-scm_c_make_gsubr (const char *name, int req, int opt, int rst, SCM (*fcn)())
+scm_c_make_gsubr (const char *name, int req, int opt, int rst, scm_t_subr fcn)
 {
   return create_subr (0, name, req, opt, rst, fcn, NULL);
 }
 
 SCM
-scm_c_define_gsubr (const char *name, int req, int opt, int rst, SCM (*fcn)())
+scm_c_define_gsubr (const char *name, int req, int opt, int rst, scm_t_subr fcn)
 {
   return create_subr (1, name, req, opt, rst, fcn, NULL);
 }
@@ -522,7 +531,7 @@ scm_c_make_gsubr_with_generic (const char *name,
 			       int req,
 			       int opt,
 			       int rst,
-			       SCM (*fcn)(),
+			       scm_t_subr fcn,
 			       SCM *gf)
 {
   return create_subr (0, name, req, opt, rst, fcn, gf);
@@ -533,7 +542,7 @@ scm_c_define_gsubr_with_generic (const char *name,
 				 int req,
 				 int opt,
 				 int rst,
-				 SCM (*fcn)(),
+				 scm_t_subr fcn,
 				 SCM *gf)
 {
   return create_subr (1, name, req, opt, rst, fcn, gf);
diff --git a/libguile/hash.c b/libguile/hash.c
index b7ad03309..cca3dd32b 100644
--- a/libguile/hash.c
+++ b/libguile/hash.c
@@ -48,7 +48,7 @@
 
 
 #ifndef floor
-extern double floor();
+extern double floor (double);
 #endif

diff --git a/libguile/init.c b/libguile/init.c
index 3df8c5ae5..37300f59a 100644
--- a/libguile/init.c
+++ b/libguile/init.c
@@ -277,7 +277,8 @@ static void *invoke_main_func(void *body_data);

 void
-scm_boot_guile (int argc, char ** argv, void (*main_func) (), void *closure)
+scm_boot_guile (int argc, char ** argv,
+                void (*main_func) (void *, int, char **), void *closure)
 {
   void *res;
   struct main_func_closure c;
diff --git a/libguile/lightening/lightening.h b/libguile/lightening/lightening.h
index b364e18cc..ecb47152a 100644
--- a/libguile/lightening/lightening.h
+++ b/libguile/lightening/lightening.h
@@ -222,7 +222,7 @@ JIT_API void* jit_end(jit_state_t*, size_t*);
 JIT_API void jit_align(jit_state_t*, unsigned);
 
 JIT_API jit_pointer_t jit_address(jit_state_t*);
-typedef void (*jit_function_pointer_t)();
+typedef void *jit_function_pointer_t;
 JIT_API jit_function_pointer_t jit_address_to_function_pointer(jit_pointer_t);
 JIT_API void jit_patch_here(jit_state_t*, jit_reloc_t);
 JIT_API void jit_patch_there(jit_state_t*, jit_reloc_t, jit_pointer_t);
diff --git a/libguile/posix.c b/libguile/posix.c
index c8bbb0f83..4fde82416 100644
--- a/libguile/posix.c
+++ b/libguile/posix.c
@@ -988,9 +988,7 @@ SCM_DEFINE (scm_getpgrp, "getpgrp", 0, 0, 0,
 	    "This is the POSIX definition, not BSD.")
 #define FUNC_NAME s_scm_getpgrp
 {
-  int (*fn)();
-  fn = (int (*) ()) getpgrp;
-  return scm_from_int (fn (0));
+  return scm_from_int (getpgrp ());
 }
 #undef FUNC_NAME
 #endif /* HAVE_GETPGRP */
diff --git a/libguile/scm.h b/libguile/scm.h
index 180b40159..de6940e04 100644
--- a/libguile/scm.h
+++ b/libguile/scm.h
@@ -810,15 +810,9 @@ enum scm_tc8_tags
 
 
 /* The type of subrs, i.e., Scheme procedures implemented in C.  Empty
-   function declarators are used internally for pointers to functions of
-   any arity.  However, these are equivalent to `(void)' in C++, are
-   obsolescent as of C99, and trigger `strict-prototypes' GCC warnings
-   (bug #23681).  */
-#ifdef BUILDING_LIBGUILE
-typedef SCM (* scm_t_subr) ();
-#else
+   function declarators are equivelent to `(void)' in C++ and C23.
+   So we must use a void pointer and cast it.  */
 typedef void *scm_t_subr;
-#endif
 
 typedef struct scm_dynamic_state scm_t_dynamic_state;
 typedef struct scm_print_state scm_print_state;
diff --git a/libguile/smob.c b/libguile/smob.c
index 8e4da9adb..4c97499fa 100644
--- a/libguile/smob.c
+++ b/libguile/smob.c
@@ -133,28 +133,28 @@ static SCM scm_smob_trampolines[16];
 static SCM
 apply_0 (SCM smob)
 {
-  SCM (*subr)() = SCM_SMOB_DESCRIPTOR (smob).apply;
+  SCM (*subr) (SCM) = SCM_SMOB_DESCRIPTOR (smob).apply;
   return subr (smob);
 }
 
 static SCM
 apply_1 (SCM smob, SCM a)
 {
-  SCM (*subr)() = SCM_SMOB_DESCRIPTOR (smob).apply;
+  SCM (*subr) (SCM, SCM) = SCM_SMOB_DESCRIPTOR (smob).apply;
   return subr (smob, a);
 }
 
 static SCM
 apply_2 (SCM smob, SCM a, SCM b)
 {
-  SCM (*subr)() = SCM_SMOB_DESCRIPTOR (smob).apply;
+  SCM (*subr) (SCM, SCM, SCM) = SCM_SMOB_DESCRIPTOR (smob).apply;
   return subr (smob, a, b);
 }
 
 static SCM
 apply_3 (SCM smob, SCM a, SCM b, SCM c)
 {
-  SCM (*subr)() = SCM_SMOB_DESCRIPTOR (smob).apply;
+  SCM (*subr) (SCM, SCM, SCM, SCM) = SCM_SMOB_DESCRIPTOR (smob).apply;
   return subr (smob, a, b, c);
 }
 
@@ -254,7 +254,7 @@ scm_set_smob_equalp (scm_t_bits tc, SCM (*equalp) (SCM, SCM))
 }
 
 void
-scm_set_smob_apply (scm_t_bits tc, SCM (*apply) (),
+scm_set_smob_apply (scm_t_bits tc, scm_t_subr apply,
 		    unsigned int req, unsigned int opt, unsigned int rst)
 {
   SCM trampoline = scm_smob_trampoline (req, opt, rst);
-- 
2.49.0