diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt index 8dcc251a4..38b35386e 100644 --- a/docs/reference/glib/glib-sections.txt +++ b/docs/reference/glib/glib-sections.txt @@ -516,6 +516,10 @@ G_CONST_RETURN G_NORETURN G_NORETURN_FUNCPTR + +G_ALWAYS_INLINE +G_NO_INLINE + G_N_ELEMENTS @@ -782,6 +786,7 @@ g_macro__has_attribute g_macro__has_builtin g_macro__has_feature g_macro__has_extension +g_macro__has_attribute___always_inline__ g_macro__has_attribute___alloc_size__ g_macro__has_attribute___const__ g_macro__has_attribute___deprecated__ diff --git a/glib/gmacros.h b/glib/gmacros.h index 8001a448e..d4e5124cf 100644 --- a/glib/gmacros.h +++ b/glib/gmacros.h @@ -212,6 +212,9 @@ * Declaring a function as `noinline` prevents the function from being * considered for inlining. * + * This macro is provided for retro-compatibility and will be eventually + * deprecated, but %G_NO_INLINE should be used instead. + * * The attribute may be placed before the declaration or definition, * right before the `static` keyword. * @@ -228,13 +231,10 @@ * [GNU C documentation](https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-noinline-function-attribute) * for more details. * + * See also: %G_NO_INLINE, %G_ALWAYS_INLINE. + * * Since: 2.58 */ -/* Note: We can’t annotate this with GLIB_AVAILABLE_MACRO_IN_2_58 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 g_macro__has_attribute(__pure__) #define G_GNUC_PURE __attribute__((__pure__)) @@ -249,9 +249,11 @@ #endif #if g_macro__has_attribute(__noinline__) -#define G_GNUC_NO_INLINE __attribute__ ((__noinline__)) +#define G_GNUC_NO_INLINE __attribute__ ((__noinline__)) \ + GLIB_AVAILABLE_MACRO_IN_2_58 #else -#define G_GNUC_NO_INLINE +#define G_GNUC_NO_INLINE \ + GLIB_AVAILABLE_MACRO_IN_2_58 #endif /** @@ -1069,6 +1071,100 @@ GLIB_AVAILABLE_MACRO_IN_2_68 #endif +/** + * G_ALWAYS_INLINE: + * + * Expands to the GNU C `always_inline` or MSVC `__forceinline` function + * attribute depending on the compiler. It is used for declaring functions + * as always inlined, ignoring the compiler optimization levels. + * + * The attribute may be placed before the declaration or definition, + * right before the `static` keyword. + * + * |[ + * G_ALWAYS_INLINE + * static int + * do_inline_this (void) + * { + * ... + * } + * ]| + * + * See the + * [GNU C documentation](https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-always_005finline-function-attribute) + * and the + * [MSVC documentation](https://docs.microsoft.com/en-us/visualstudio/misc/inline-inline-forceinline) + * + * Since: 2.74 + */ +/* Note: We can’t annotate this with GLIB_AVAILABLE_MACRO_IN_2_74 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 g_macro__has_attribute(__always_inline__) +# if defined (__cplusplus) && __cplusplus >= 201103L + /* Use ISO C++11 syntax when the compiler supports it. */ +# define G_ALWAYS_INLINE [[gnu::always_inline]] +# else +# define G_ALWAYS_INLINE __attribute__ ((__always_inline__)) +# endif +#elif defined (_MSC_VER) + /* Use MSVC specific syntax. */ +# define G_ALWAYS_INLINE __forceinline +#else +# define G_ALWAYS_INLINE /* empty */ +#endif + +/** + * G_NO_INLINE: + * + * Expands to the GNU C or MSVC `noinline` function attribute + * depending on the compiler. It is used for declaring functions + * preventing from being considered for inlining. + * + * Note that %G_NO_INLINE supersedes the previous %G_GNUC_NO_INLINE + * macro, which will eventually be deprecated. + * %G_NO_INLINE supports more platforms. + * + * The attribute may be placed before the declaration or definition, + * right before the `static` keyword. + * + * |[ + * G_NO_INLINE + * static int + * do_not_inline_this (void) + * { + * ... + * } + * ]| + * + * Since: 2.74 + */ +/* Note: We can’t annotate this with GLIB_AVAILABLE_MACRO_IN_2_74 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 g_macro__has_attribute(__noinline__) +# if defined (__cplusplus) && __cplusplus >= 201103L + /* Use ISO C++11 syntax when the compiler supports it. */ +# define G_NO_INLINE [[gnu::noinline]] +# else +# define G_NO_INLINE __attribute__ ((__noinline__)) +# endif +#elif defined (_MSC_VER) && (1200 <= _MSC_VER) + /* Use MSVC specific syntax. */ +# if defined (__cplusplus) && __cplusplus >= 201103L + /* Use ISO C++11 syntax when the compiler supports it. */ +# define G_NO_INLINE [[msvc::noinline]] +# else +# define G_NO_INLINE __declspec (noinline) +# endif +#else +# define G_NO_INLINE /* empty */ +#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/glib/gthread-posix.c b/glib/gthread-posix.c index 751533f56..fbf7531fe 100644 --- a/glib/gthread-posix.c +++ b/glib/gthread-posix.c @@ -1490,7 +1490,8 @@ g_mutex_clear (GMutex *mutex) } } -static void __attribute__((noinline)) +G_GNUC_NO_INLINE +static void g_mutex_lock_slowpath (GMutex *mutex) { /* Set to contended. If it was empty before then we @@ -1505,7 +1506,8 @@ g_mutex_lock_slowpath (GMutex *mutex) } } -static void __attribute__((noinline)) +G_GNUC_NO_INLINE +static void g_mutex_unlock_slowpath (GMutex *mutex, guint prev) { diff --git a/glib/tests/cxx.cpp b/glib/tests/cxx.cpp index 7300a738e..08ed8e81b 100644 --- a/glib/tests/cxx.cpp +++ b/glib/tests/cxx.cpp @@ -160,6 +160,30 @@ test_atomic_int_exchange (void) #endif } +G_NO_INLINE +static gboolean +do_not_inline_this (void) +{ + return FALSE; +} + +G_ALWAYS_INLINE +static inline gboolean +do_inline_this (void) +{ + return TRUE; +} + +static void +test_inline_no_inline_macros (void) +{ + g_test_message ("Test that G_NO_INLINE and G_ALWAYS_INLINE functions " + "can be compiled with C++ compiler"); + + g_assert_false (do_not_inline_this ()); + g_assert_true (do_inline_this ()); +} + int main (int argc, char *argv[]) { @@ -176,6 +200,7 @@ main (int argc, char *argv[]) g_test_add_func ("/C++/atomic-int-compare-and-exchange-full", test_atomic_int_compare_and_exchange_full); g_test_add_func ("/C++/atomic-pointer-exchange", test_atomic_pointer_exchange); g_test_add_func ("/C++/atomic-int-exchange", test_atomic_int_exchange); + g_test_add_func ("/C++/inlined-not-inlined-functions", test_inline_no_inline_macros); return g_test_run (); } diff --git a/gobject/gtype.h b/gobject/gtype.h index 6f072d3a8..3f2afb31e 100644 --- a/gobject/gtype.h +++ b/gobject/gtype.h @@ -2160,7 +2160,7 @@ type_name##_get_type (void) \ return static_g_define_type_id; \ } /* closes type_name##_get_type() */ \ \ -G_GNUC_NO_INLINE \ +G_NO_INLINE \ static GType \ type_name##_get_type_once (void) \ { \ @@ -2329,7 +2329,7 @@ type_name##_get_type (void) \ return static_g_define_type_id; \ } \ \ -G_GNUC_NO_INLINE \ +G_NO_INLINE \ static GType \ type_name##_get_type_once (void) \ { \ @@ -2366,7 +2366,7 @@ type_name##_get_type (void) \ return static_g_define_type_id; \ } \ \ -G_GNUC_NO_INLINE \ +G_NO_INLINE \ static GType \ type_name##_get_type_once (void) \ { \ @@ -2419,7 +2419,7 @@ type_name##_get_type (void) \ return static_g_define_type_id; \ } \ \ -G_GNUC_NO_INLINE \ +G_NO_INLINE \ static GType \ type_name##_get_type_once (void) \ { \