[glib: 1/4] gmacros: Provide platform-independent G_ALWAYS_INLINE and G_NO_INLINE




commit 15cd0f04612c90292792c4d123ebe84bf4bf93a6
Author: Marco Trevisan (Treviño) <mail 3v1n0 net>
Date:   Fri Jun 24 14:44:02 2022 +0200

    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.

 docs/reference/glib/glib-sections.txt |  5 ++
 glib/gmacros.h                        | 99 +++++++++++++++++++++++++++++++++++
 glib/tests/cxx.cpp                    | 25 +++++++++
 3 files changed, 129 insertions(+)
---
diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt
index 8dcc251a46..38b35386e3 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
 
+<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__
diff --git a/glib/gmacros.h b/glib/gmacros.h
index 8001a448e8..218ee4f25f 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,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 can’t annotate this with GLIB_AVAILABLE_MACRO_IN_2_58 because it’s
@@ -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 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.
+ *
+ * |[<!-- language="C" -->
+ * 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/tests/cxx.cpp b/glib/tests/cxx.cpp
index 363700d14f..bab5aa9c5f 100644
--- a/glib/tests/cxx.cpp
+++ b/glib/tests/cxx.cpp
@@ -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 ();
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]