From 039fa6897bb4c5cd30caec8ee3add1a4ef612f76 Mon Sep 17 00:00:00 2001 From: Will Thompson Date: Fri, 8 Jun 2018 13:29:42 +0100 Subject: [PATCH] Add G_SOURCE_FUNC cast macro which suppresses -Wcast-function-type This is the workaround suggested by https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wcast-function-type This warning is not enabled by default during the GLib build, but applications may want to opt into it. --- docs/reference/glib/glib-sections.txt | 1 + glib/gmain.c | 3 ++- glib/gmain.h | 22 ++++++++++++++++++++++ glib/tests/mainloop.c | 16 +++++++++++++++- 4 files changed, 40 insertions(+), 2 deletions(-) diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt index 0183b0898..ef0b2e643 100644 --- a/docs/reference/glib/glib-sections.txt +++ b/docs/reference/glib/glib-sections.txt @@ -621,6 +621,7 @@ g_source_set_name_by_id g_source_get_context g_source_set_callback GSourceFunc +G_SOURCE_FUNC g_source_set_callback_indirect g_source_set_ready_time g_source_get_ready_time diff --git a/glib/gmain.c b/glib/gmain.c index cdc86547e..7d49025c7 100644 --- a/glib/gmain.c +++ b/glib/gmain.c @@ -1628,7 +1628,8 @@ g_source_set_callback_indirect (GSource *source, * * The exact type of @func depends on the type of source; ie. you * should not count on @func being called with @data as its first - * parameter. + * parameter. Cast @func with G_SOURCE_FUNC() to avoid warnings about + * incompatible function types. * * See [memory management of sources][mainloop-memory-management] for details * on how to handle memory management of @data. diff --git a/glib/gmain.h b/glib/gmain.h index 2515d7326..de6a73ac9 100644 --- a/glib/gmain.h +++ b/glib/gmain.h @@ -163,11 +163,33 @@ typedef struct _GSourceFuncs GSourceFuncs; * Specifies the type of function passed to g_timeout_add(), * g_timeout_add_full(), g_idle_add(), and g_idle_add_full(). * + * When calling g_source_set_callback(), you may need to cast a function of a + * different type to this type. Use G_SOURCE_FUNC() to avoid warnings about + * incompatible function types. + * * Returns: %FALSE if the source should be removed. #G_SOURCE_CONTINUE and * #G_SOURCE_REMOVE are more memorable names for the return value. */ typedef gboolean (*GSourceFunc) (gpointer user_data); +/** + * G_SOURCE_FUNC: + * @f: a function pointer. + * + * Cast a function pointer to a #GSourceFunc, suppressing warnings from GCC 8 + * onwards with `-Wextra` or `-Wcast-function-type` enabled about the function + * types being incompatible. + * + * For example, the correct type of callback for a source created by + * g_child_watch_source_new() is #GChildWatchFunc, which accepts more arguments + * than #GSourceFunc. Casting the function with `(GSourceFunc)` to call + * g_source_set_callback() will trigger a warning, even though it will be cast + * back to the correct type before it is called by the source. + * + * Since: 2.58 + */ +#define G_SOURCE_FUNC(f) ((GSourceFunc) (void (*)(void)) (f)) + /** * GChildWatchFunc: * @pid: the process id of the child process diff --git a/glib/tests/mainloop.c b/glib/tests/mainloop.c index 6b0074011..cf114fd40 100644 --- a/glib/tests/mainloop.c +++ b/glib/tests/mainloop.c @@ -1306,7 +1306,21 @@ test_unix_fd_source (void) out = in = FALSE; out_source = g_unix_fd_source_new (fds[1], G_IO_OUT); - g_source_set_callback (out_source, (GSourceFunc) flag_bool, &out, NULL); + /* -Wcast-function-type complains about casting 'flag_bool' to GSourceFunc. + * GCC has no way of knowing that it will be cast back to GUnixFDSourceFunc + * before being called. Although GLib itself is not compiled with + * -Wcast-function-type, applications that use GLib may well be (since + * -Wextra includes it), so we provide a G_SOURCE_FUNC() macro to suppress + * the warning. We check that it works here. + */ +#if G_GNUC_CHECK_VERSION(8, 0) +#pragma GCC diagnostic push +#pragma GCC diagnostic error "-Wcast-function-type" +#endif + g_source_set_callback (out_source, G_SOURCE_FUNC (flag_bool), &out, NULL); +#if G_GNUC_CHECK_VERSION(8, 0) +#pragma GCC diagnostic pop +#endif g_source_attach (out_source, NULL); assert_main_context_state (1, fds[1], G_IO_OUT, 0);