Merge branch 'inline-macros' into 'main'

gmacros: Provide platform-independent G_ALWAYS_INLINE and G_NO_INLINE

See merge request GNOME/glib!2781
This commit is contained in:
Philip Withnall 2022-07-06 13:40:10 +00:00
commit 8385f52db7
5 changed files with 141 additions and 13 deletions

View File

@ -516,6 +516,10 @@ G_CONST_RETURN
G_NORETURN G_NORETURN
G_NORETURN_FUNCPTR G_NORETURN_FUNCPTR
<SUBSECTION>
G_ALWAYS_INLINE
G_NO_INLINE
<SUBSECTION> <SUBSECTION>
G_N_ELEMENTS G_N_ELEMENTS
</SECTION> </SECTION>
@ -782,6 +786,7 @@ g_macro__has_attribute
g_macro__has_builtin g_macro__has_builtin
g_macro__has_feature g_macro__has_feature
g_macro__has_extension g_macro__has_extension
g_macro__has_attribute___always_inline__
g_macro__has_attribute___alloc_size__ g_macro__has_attribute___alloc_size__
g_macro__has_attribute___const__ g_macro__has_attribute___const__
g_macro__has_attribute___deprecated__ g_macro__has_attribute___deprecated__

View File

@ -212,6 +212,9 @@
* Declaring a function as `noinline` prevents the function from being * Declaring a function as `noinline` prevents the function from being
* considered for inlining. * 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, * The attribute may be placed before the declaration or definition,
* right before the `static` keyword. * 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) * [GNU C documentation](https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-noinline-function-attribute)
* for more details. * for more details.
* *
* See also: %G_NO_INLINE, %G_ALWAYS_INLINE.
*
* Since: 2.58 * Since: 2.58
*/ */
/* Note: We cant annotate this with GLIB_AVAILABLE_MACRO_IN_2_58 because its
* 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 doesnt use the new
* macro itself. */
#if g_macro__has_attribute(__pure__) #if g_macro__has_attribute(__pure__)
#define G_GNUC_PURE __attribute__((__pure__)) #define G_GNUC_PURE __attribute__((__pure__))
@ -249,9 +249,11 @@
#endif #endif
#if g_macro__has_attribute(__noinline__) #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 #else
#define G_GNUC_NO_INLINE #define G_GNUC_NO_INLINE \
GLIB_AVAILABLE_MACRO_IN_2_58
#endif #endif
/** /**
@ -1069,6 +1071,100 @@
GLIB_AVAILABLE_MACRO_IN_2_68 GLIB_AVAILABLE_MACRO_IN_2_68
#endif #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.
*
* |[<!-- language="C" -->
* 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 cant annotate this with GLIB_AVAILABLE_MACRO_IN_2_74 because its
* 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 doesnt 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.
*
* |[<!-- language="C" -->
* G_NO_INLINE
* static int
* do_not_inline_this (void)
* {
* ...
* }
* ]|
*
* Since: 2.74
*/
/* Note: We cant annotate this with GLIB_AVAILABLE_MACRO_IN_2_74 because its
* 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 doesnt 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 G_LIKELY and G_UNLIKELY macros let the programmer give hints to
* the compiler about the expected result of an expression. Some compilers * the compiler about the expected result of an expression. Some compilers

View File

@ -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) g_mutex_lock_slowpath (GMutex *mutex)
{ {
/* Set to contended. If it was empty before then we /* 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, g_mutex_unlock_slowpath (GMutex *mutex,
guint prev) guint prev)
{ {

View File

@ -160,6 +160,30 @@ test_atomic_int_exchange (void)
#endif #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 int
main (int argc, char *argv[]) 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-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-pointer-exchange", test_atomic_pointer_exchange);
g_test_add_func ("/C++/atomic-int-exchange", test_atomic_int_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 (); return g_test_run ();
} }

View File

@ -2160,7 +2160,7 @@ type_name##_get_type (void) \
return static_g_define_type_id; \ return static_g_define_type_id; \
} /* closes type_name##_get_type() */ \ } /* closes type_name##_get_type() */ \
\ \
G_GNUC_NO_INLINE \ G_NO_INLINE \
static GType \ static GType \
type_name##_get_type_once (void) \ type_name##_get_type_once (void) \
{ \ { \
@ -2329,7 +2329,7 @@ type_name##_get_type (void) \
return static_g_define_type_id; \ return static_g_define_type_id; \
} \ } \
\ \
G_GNUC_NO_INLINE \ G_NO_INLINE \
static GType \ static GType \
type_name##_get_type_once (void) \ type_name##_get_type_once (void) \
{ \ { \
@ -2366,7 +2366,7 @@ type_name##_get_type (void) \
return static_g_define_type_id; \ return static_g_define_type_id; \
} \ } \
\ \
G_GNUC_NO_INLINE \ G_NO_INLINE \
static GType \ static GType \
type_name##_get_type_once (void) \ type_name##_get_type_once (void) \
{ \ { \
@ -2419,7 +2419,7 @@ type_name##_get_type (void) \
return static_g_define_type_id; \ return static_g_define_type_id; \
} \ } \
\ \
G_GNUC_NO_INLINE \ G_NO_INLINE \
static GType \ static GType \
type_name##_get_type_once (void) \ type_name##_get_type_once (void) \
{ \ { \