gmacros: Provide platform-independent G_ALWAYS_INLINE and G_NO_INLINE

We had gcc-only implementations for them while both can be used in all
the supported platforms we have.

So let's just provide generic definitions, while we keep the old ones
for both consistency and retro-compatibility.
This commit is contained in:
Marco Trevisan (Treviño) 2022-06-24 14:44:02 +02:00
parent b5231ed003
commit 15cd0f0461
3 changed files with 129 additions and 0 deletions

View File

@ -516,6 +516,10 @@ G_CONST_RETURN
G_NORETURN
G_NORETURN_FUNCPTR
<SUBSECTION>
G_ALWAYS_INLINE
G_NO_INLINE
<SUBSECTION>
G_N_ELEMENTS
</SECTION>
@ -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__

View File

@ -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,6 +231,8 @@
* [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 cant annotate this with GLIB_AVAILABLE_MACRO_IN_2_58 because its
@ -1069,6 +1074,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.
*
* |[<!-- 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 compiler about the expected result of an expression. Some compilers

View File

@ -158,6 +158,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[])
{
@ -174,6 +198,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 ();
}