From c1d74e35c18aae1ffb2959e4e8c9d1e8c60103ba Mon Sep 17 00:00:00 2001 From: Emmanuel Fleury Date: Sun, 1 Sep 2019 22:16:13 +0200 Subject: [PATCH 1/3] Adding macros G_NORETURN and G_NORETURN_FUNCPTR This macro is borrowed from the gnulib project in the 'noreturn.h' file. Fixes: #994 --- docs/reference/glib/glib-sections.txt | 2 + glib/gmacros.h | 70 +++++++++++++++++++++++++++ msvc_recommended_pragmas.h | 5 ++ 3 files changed, 77 insertions(+) diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt index 81a3e0c24..690c0de9c 100644 --- a/docs/reference/glib/glib-sections.txt +++ b/docs/reference/glib/glib-sections.txt @@ -469,6 +469,8 @@ G_ALIGNOF G_CONST_RETURN +G_NORETURN +G_NORETURN_FUNCPTR G_N_ELEMENTS diff --git a/glib/gmacros.h b/glib/gmacros.h index d294fa90f..e5cd32eca 100644 --- a/glib/gmacros.h +++ b/glib/gmacros.h @@ -917,6 +917,76 @@ #define G_CONST_RETURN const GLIB_DEPRECATED_MACRO_IN_2_30_FOR(const) #endif +/** + * G_NORETURN: + * + * Expands to the GNU C or MSVC `noreturn` function attribute depending on + * the compiler. It is used for declaring functions which never return. + * Enables optimization of the function, and avoids possible compiler warnings. + * + * Note that %G_NORETURN supersedes the previous %G_GNUC_NORETURN macro, which + * will eventually be deprecated. %G_NORETURN supports more platforms. + * + * Place the attribute before the function declaration as follows: + * + * |[ + * G_NORETURN void g_abort (void); + * ]| + * + * Since: 2.68 + */ +/* Note: We can’t annotate this with GLIB_AVAILABLE_MACRO_IN_2_68 because it’s + * used within the GLib headers in function declarations which are always + * evaluated when a header is included. This results in warnings in third party + * code which includes glib.h, even if the third party code doesn’t use the new + * macro itself. */ +#if (3 <= __GNUC__ || (__GNUC__ == 2 && 8 <= __GNUC_MINOR__)) || (0x5110 <= __SUNPRO_C) + /* For compatibility with G_NORETURN_FUNCPTR on clang, use + __attribute__((__noreturn__)), not _Noreturn. */ +# define G_NORETURN __attribute__ ((__noreturn__)) +#elif 1200 <= _MSC_VER + /* Use MSVC specific syntax. */ +# define G_NORETURN __declspec (noreturn) + /* Use ISO C++11 syntax when the compiler supports it. */ +#elif (__cplusplus >= 201103 && !(__GNUC__ == 4 && __GNUC_MINOR__ == 7)) || (_MSC_VER >= 1900) +# define G_NORETURN [[noreturn]] + /* Use ISO C11 syntax when the compiler supports it. */ +#elif __STDC_VERSION__ >= 201112 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) +# define G_NORETURN _Noreturn +#else +# define G_NORETURN /* empty */ +#endif + +/** + * G_NORETURN_FUNCPTR: + * + * Expands to the GNU C or MSVC `noreturn` function attribute depending on + * the compiler. It is used for declaring function pointers which never return. + * Enables optimization of the function, and avoids possible compiler warnings. + * + * Place the attribute before the function declaration as follows: + * + * |[ + * G_NORETURN_FUNCPTR void (*funcptr) (void); + * ]| + * + * Note that if the function is not a function pointer, you can simply use + * the %G_NORETURN macro as follows: + * + * |[ + * G_NORETURN void g_abort (void); + * ]| + * + * Since: 2.68 + */ +#if (3 <= __GNUC__ || (__GNUC__ == 2 && 8 <= __GNUC_MINOR__)) || (0x5110 <= __SUNPRO_C) +# define G_NORETURN_FUNCPTR __attribute__ ((__noreturn__)) \ + GLIB_AVAILABLE_MACRO_IN_2_68 +#else +# define G_NORETURN_FUNCPTR /* empty */ \ + GLIB_AVAILABLE_MACRO_IN_2_68 +#endif + /* * The G_LIKELY and G_UNLIKELY macros let the programmer give hints to * the compiler about the expected result of an expression. Some compilers diff --git a/msvc_recommended_pragmas.h b/msvc_recommended_pragmas.h index c0eb1d5ed..e70698712 100644 --- a/msvc_recommended_pragmas.h +++ b/msvc_recommended_pragmas.h @@ -24,6 +24,11 @@ #pragma warning(disable:4101) /* unreferenced local variable */ #pragma warning(error:4150) +/* G_NORETURN */ +#pragma warning(error:4646) /* function declared with __declspec(noreturn) has non-void return type */ +#pragma warning(error:4715) /* 'function': not all control paths return a value */ +#pragma warning(error:4098) /* 'void' function returning a value */ + #pragma warning(disable:4244) /* No possible loss of data warnings */ #pragma warning(disable:4305) /* No truncation from int to char warnings */ From 76426c0158323ab96b0991a4ed69358ed1c8e7e2 Mon Sep 17 00:00:00 2001 From: Emmanuel Fleury Date: Tue, 3 Sep 2019 19:43:41 +0200 Subject: [PATCH 2/3] Rewriting the G_GNUC_NORETURN into G_NORETURN macros everywhere --- gio/tests/proxy.c | 2 +- gio/tests/resolver.c | 2 +- glib/gmessages.h | 5 +++-- glib/goption.c | 2 +- glib/gspawn.c | 2 +- glib/gtestutils.h | 3 ++- glib/gutils.h | 2 +- 7 files changed, 10 insertions(+), 8 deletions(-) diff --git a/gio/tests/proxy.c b/gio/tests/proxy.c index 50a20622e..e64355ae0 100644 --- a/gio/tests/proxy.c +++ b/gio/tests/proxy.c @@ -37,7 +37,7 @@ static const gchar *info = NULL; static GCancellable *cancellable = NULL; static gint return_value = 0; -static void G_GNUC_NORETURN +static G_NORETURN void usage (void) { fprintf (stderr, "Usage: proxy [-s] (uri|host:port|ip:port|path|srv/protocol/domain)\n"); diff --git a/gio/tests/resolver.c b/gio/tests/resolver.c index c57b81867..3e6d89670 100644 --- a/gio/tests/resolver.c +++ b/gio/tests/resolver.c @@ -40,7 +40,7 @@ static gboolean synchronous = FALSE; static guint connectable_count = 0; static GResolverRecordType record_type = 0; -static void G_GNUC_NORETURN +static G_NORETURN void usage (void) { fprintf (stderr, "Usage: resolver [-s] [hostname | IP | service/protocol/domain ] ...\n"); diff --git a/glib/gmessages.h b/glib/gmessages.h index 2e3650baf..43c6d67b9 100644 --- a/glib/gmessages.h +++ b/glib/gmessages.h @@ -283,11 +283,12 @@ void g_warn_message (const char *domain, const char *func, const char *warnexpr) G_ANALYZER_NORETURN; GLIB_DEPRECATED +G_NORETURN void g_assert_warning (const char *log_domain, const char *file, const int line, const char *pretty_function, - const char *expression) G_GNUC_NORETURN; + const char *expression); GLIB_AVAILABLE_IN_2_56 void g_log_structured_standard (const gchar *log_domain, @@ -399,7 +400,7 @@ void g_log_structured_standard (const gchar *log_domain, format) #endif #else /* no varargs macros */ -static void g_error (const gchar *format, ...) G_GNUC_NORETURN G_ANALYZER_NORETURN; +static G_NORETURN void g_error (const gchar *format, ...) G_ANALYZER_NORETURN; static void g_critical (const gchar *format, ...) G_ANALYZER_NORETURN; static inline void diff --git a/glib/goption.c b/glib/goption.c index bb9093a33..a351f84cb 100644 --- a/glib/goption.c +++ b/glib/goption.c @@ -1091,7 +1091,7 @@ g_option_context_get_help (GOptionContext *context, return g_string_free (string, FALSE); } -G_GNUC_NORETURN +G_NORETURN static void print_help (GOptionContext *context, gboolean main_help, diff --git a/glib/gspawn.c b/glib/gspawn.c index e720635db..fa3cfe7c0 100644 --- a/glib/gspawn.c +++ b/glib/gspawn.c @@ -1116,7 +1116,7 @@ write_all (gint fd, gconstpointer vbuf, gsize to_write) /* This function is called between fork() and exec() and hence must be * async-signal-safe (see signal-safety(7)). */ -G_GNUC_NORETURN +G_NORETURN static void write_err_and_exit (gint fd, gint msg) { diff --git a/glib/gtestutils.h b/glib/gtestutils.h index c7a0c5969..e93c49067 100644 --- a/glib/gtestutils.h +++ b/glib/gtestutils.h @@ -514,11 +514,12 @@ void g_assertion_message (const char *domain, const char *func, const char *message) G_ANALYZER_NORETURN; GLIB_AVAILABLE_IN_ALL +G_NORETURN void g_assertion_message_expr (const char *domain, const char *file, int line, const char *func, - const char *expr) G_GNUC_NORETURN; + const char *expr); GLIB_AVAILABLE_IN_ALL void g_assertion_message_cmpstr (const char *domain, const char *file, diff --git a/glib/gutils.h b/glib/gutils.h index 8a927d0b3..f8a6049ff 100644 --- a/glib/gutils.h +++ b/glib/gutils.h @@ -434,7 +434,7 @@ g_bit_storage_impl (gulong number) # define g_abort() abort () #else GLIB_AVAILABLE_IN_2_50 -void g_abort (void) G_GNUC_NORETURN G_ANALYZER_NORETURN; +G_NORETURN void g_abort (void) G_ANALYZER_NORETURN; #endif #endif From 9cccc08b82d1df43c96e1fc1eb97ee6b1e2e30c5 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Wed, 25 Nov 2020 11:37:06 +0000 Subject: [PATCH 3/3] gmacros: Document soft-deprecation of G_GNUC_NORETURN MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It still works, and deprecating it would be quite disruptive (as it’s used in headers), so amend the documentation to point people to `G_NORETURN` instead. Signed-off-by: Philip Withnall Helps: #994 --- glib/gmacros.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/glib/gmacros.h b/glib/gmacros.h index e5cd32eca..65f3738a6 100644 --- a/glib/gmacros.h +++ b/glib/gmacros.h @@ -423,6 +423,12 @@ * It is used for declaring functions which never return. It enables * optimization of the function, and avoids possible compiler warnings. * + * Since 2.68, it is recommended that code uses %G_NORETURN instead of + * %G_GNUC_NORETURN, as that works on more platforms and compilers (in + * particular, MSVC and C++11) than %G_GNUC_NORETURN, which works with GCC and + * Clang only. %G_GNUC_NORETURN continues to work, so has not been deprecated + * yet. + * * Place the attribute after the declaration, just before the semicolon. * * |[