[glib: 1/3] gmacros.h: use g_macro__has_attribute() where possible




commit 2b9bf7b16294041d6259cd29c98d8debe1a11be2
Author: Aleksandr Mezin <mezin alexander gmail com>
Date:   Fri Apr 9 17:13:09 2021 +0600

    gmacros.h: use g_macro__has_attribute() where possible
    
    Fall back to compiler version checks only when `__has_attribute()` is not
    available.
    
    clang-cl doesn't define `__GNU__`, but still accepts attributes. This change
    gets rid of a lot of warnings when building GLib with clang-cl. For GCC and
    non-cl Clang nothing should change.

 docs/reference/glib/glib-sections.txt |  15 ++++
 glib/gmacros.h                        | 127 +++++++++++++++++++++++++---------
 2 files changed, 109 insertions(+), 33 deletions(-)
---
diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt
index db0e554e7..dff212e4d 100644
--- a/docs/reference/glib/glib-sections.txt
+++ b/docs/reference/glib/glib-sections.txt
@@ -754,6 +754,21 @@ g_macro__has_attribute
 g_macro__has_builtin
 g_macro__has_feature
 g_macro__has_extension
+g_macro__has_attribute___alloc_size__
+g_macro__has_attribute___const__
+g_macro__has_attribute___deprecated__
+g_macro__has_attribute___format__
+g_macro__has_attribute___format_arg__
+g_macro__has_attribute___malloc__
+g_macro__has_attribute___no_instrument_function__
+g_macro__has_attribute___noreturn__
+g_macro__has_attribute___pure__
+g_macro__has_attribute___sentinel__
+g_macro__has_attribute___unused__
+g_macro__has_attribute_fallthrough
+g_macro__has_attribute_may_alias
+g_macro__has_attribute_noinline
+g_macro__has_attribute_warn_unused_result
 </SECTION>
 
 <SECTION>
diff --git a/glib/gmacros.h b/glib/gmacros.h
index 5bba1d77e..1c2dd6897 100644
--- a/glib/gmacros.h
+++ b/glib/gmacros.h
@@ -37,6 +37,12 @@
  */
 #include <stddef.h>
 
+/*
+ * Note: Clang (but not clang-cl) defines __GNUC__ and __GNUC_MINOR__.
+ * Both Clang 11.1 on current Arch Linux and Apple's Clang 12.0 define
+ * __GNUC__ = 4 and __GNUC_MINOR__ = 2. So G_GNUC_CHECK_VERSION(4, 2) on
+ * current Clang will be 1.
+ */
 #ifdef __GNUC__
 #define G_GNUC_CHECK_VERSION(major, minor) \
     ((__GNUC__ > (major)) || \
@@ -106,6 +112,39 @@
 #  define G_INLINE_FUNC static inline GLIB_DEPRECATED_MACRO_IN_2_48_FOR(static inline)
 #endif /* G_IMPLEMENT_INLINES */
 
+/*
+ * Attribute support detection. Works on clang and GCC >= 5
+ * https://clang.llvm.org/docs/LanguageExtensions.html#has-attribute
+ * https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005fattribute.html
+ */
+
+#ifdef __has_attribute
+#define g_macro__has_attribute __has_attribute
+#else
+
+/*
+ * Fallback for GCC < 5 and other compilers not supporting __has_attribute.
+ */
+#define g_macro__has_attribute(x) g_macro__has_attribute_##x
+
+#define g_macro__has_attribute___pure__ G_GNUC_CHECK_VERSION (2, 96)
+#define g_macro__has_attribute___malloc__ G_GNUC_CHECK_VERSION (2, 96)
+#define g_macro__has_attribute_noinline G_GNUC_CHECK_VERSION (2, 96)
+#define g_macro__has_attribute___sentinel__ G_GNUC_CHECK_VERSION (4, 0)
+#define g_macro__has_attribute___alloc_size__ G_GNUC_CHECK_VERSION (4, 3)
+#define g_macro__has_attribute___format__ G_GNUC_CHECK_VERSION (2, 4)
+#define g_macro__has_attribute___format_arg__ G_GNUC_CHECK_VERSION (2, 4)
+#define g_macro__has_attribute___noreturn__ G_GNUC_CHECK_VERSION (2, 4)
+#define g_macro__has_attribute___const__ G_GNUC_CHECK_VERSION (2, 4)
+#define g_macro__has_attribute___unused__ G_GNUC_CHECK_VERSION (2, 4)
+#define g_macro__has_attribute___no_instrument_function__ G_GNUC_CHECK_VERSION (2, 4)
+#define g_macro__has_attribute_fallthrough G_GNUC_CHECK_VERSION (6, 0)
+#define g_macro__has_attribute___deprecated__ G_GNUC_CHECK_VERSION (3, 1)
+#define g_macro__has_attribute_may_alias G_GNUC_CHECK_VERSION (3, 3)
+#define g_macro__has_attribute_warn_unused_result G_GNUC_CHECK_VERSION (3, 4)
+
+#endif
+
 /* Provide macros to feature the GCC function attribute.
  */
 
@@ -194,13 +233,21 @@
  * code which includes glib.h, even if the third party code doesn’t use the new
  * macro itself. */
 
-#if G_GNUC_CHECK_VERSION(2, 96)
+#if g_macro__has_attribute(__pure__)
 #define G_GNUC_PURE __attribute__((__pure__))
-#define G_GNUC_MALLOC __attribute__((__malloc__))
-#define G_GNUC_NO_INLINE __attribute__((noinline))
 #else
 #define G_GNUC_PURE
+#endif
+
+#if g_macro__has_attribute(__malloc__)
+#define G_GNUC_MALLOC __attribute__ ((__malloc__))
+#else
 #define G_GNUC_MALLOC
+#endif
+
+#if g_macro__has_attribute(noinline)
+#define G_GNUC_NO_INLINE __attribute__ ((noinline))
+#else
 #define G_GNUC_NO_INLINE
 #endif
 
@@ -223,7 +270,7 @@
  *
  * Since: 2.8
  */
-#if G_GNUC_CHECK_VERSION(4, 0)
+#if g_macro__has_attribute(__sentinel__)
 #define G_GNUC_NULL_TERMINATED __attribute__((__sentinel__))
 #else
 #define G_GNUC_NULL_TERMINATED
@@ -261,12 +308,6 @@
  * So we define it to 0 to satisfy the pre-processor.
  */
 
-#ifdef __has_attribute
-#define g_macro__has_attribute __has_attribute
-#else
-#define g_macro__has_attribute(x) 0
-#endif
-
 #ifdef __has_feature
 #define g_macro__has_feature __has_feature
 #else
@@ -328,8 +369,7 @@
  *
  * Since: 2.18
  */
-#if (!defined(__clang__) && G_GNUC_CHECK_VERSION(4, 3)) || \
-    (defined(__clang__) && g_macro__has_attribute(__alloc_size__))
+#if g_macro__has_attribute(__alloc_size__)
 #define G_GNUC_ALLOC_SIZE(x) __attribute__((__alloc_size__(x)))
 #define G_GNUC_ALLOC_SIZE2(x,y) __attribute__((__alloc_size__(x,y)))
 #else
@@ -515,7 +555,8 @@
  * See the [GNU C 
documentation](https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-no_005finstrument_005ffunction-function-attribute)
 for more details.
  */
 
-#if G_GNUC_CHECK_VERSION(2, 4)
+#if g_macro__has_attribute(__format__)
+
 #if !defined (__clang__) && G_GNUC_CHECK_VERSION (4, 4)
 #define G_GNUC_PRINTF( format_idx, arg_idx )    \
   __attribute__((__format__ (gnu_printf, format_idx, arg_idx)))
@@ -533,31 +574,54 @@
   __attribute__((__format__ (__strftime__, format_idx, 0))) \
   GLIB_AVAILABLE_MACRO_IN_2_60
 #endif
-#define G_GNUC_FORMAT( arg_idx )                \
-  __attribute__((__format_arg__ (arg_idx)))
-#define G_GNUC_NORETURN                         \
-  __attribute__((__noreturn__))
-#define G_GNUC_CONST                            \
-  __attribute__((__const__))
-#define G_GNUC_UNUSED                           \
-  __attribute__((__unused__))
-#define G_GNUC_NO_INSTRUMENT                   \
-  __attribute__((__no_instrument_function__))
-#else   /* !__GNUC__ */
+
+#else
+
 #define G_GNUC_PRINTF( format_idx, arg_idx )
 #define G_GNUC_SCANF( format_idx, arg_idx )
 #define G_GNUC_STRFTIME( format_idx ) \
   GLIB_AVAILABLE_MACRO_IN_2_60
+
+#endif
+
+#if g_macro__has_attribute(__format_arg__)
+#define G_GNUC_FORMAT(arg_idx) \
+  __attribute__ ((__format_arg__ (arg_idx)))
+#else
 #define G_GNUC_FORMAT( arg_idx )
+#endif
+
+#if g_macro__has_attribute(__noreturn__)
+#define G_GNUC_NORETURN \
+  __attribute__ ((__noreturn__))
+#else
 /* NOTE: MSVC has __declspec(noreturn) but unlike GCC __attribute__,
  * __declspec can only be placed at the start of the function prototype
  * and not at the end, so we can't use it without breaking API.
  */
 #define G_GNUC_NORETURN
+#endif
+
+#if g_macro__has_attribute(__const__)
+#define G_GNUC_CONST \
+  __attribute__ ((__const__))
+#else
 #define G_GNUC_CONST
+#endif
+
+#if g_macro__has_attribute(__unused__)
+#define G_GNUC_UNUSED \
+  __attribute__ ((__unused__))
+#else
 #define G_GNUC_UNUSED
+#endif
+
+#if g_macro__has_attribute(__no_instrument_function__)
+#define G_GNUC_NO_INSTRUMENT \
+  __attribute__ ((__no_instrument_function__))
+#else
 #define G_GNUC_NO_INSTRUMENT
-#endif  /* !__GNUC__ */
+#endif
 
 /**
  * G_GNUC_FALLTHROUGH:
@@ -587,16 +651,13 @@
  *
  * Since: 2.60
  */
-#if G_GNUC_CHECK_VERSION(6, 0)
-#define G_GNUC_FALLTHROUGH __attribute__((fallthrough)) \
-  GLIB_AVAILABLE_MACRO_IN_2_60
-#elif g_macro__has_attribute (fallthrough)
+#if g_macro__has_attribute(fallthrough)
 #define G_GNUC_FALLTHROUGH __attribute__((fallthrough)) \
   GLIB_AVAILABLE_MACRO_IN_2_60
 #else
 #define G_GNUC_FALLTHROUGH \
   GLIB_AVAILABLE_MACRO_IN_2_60
-#endif /* __GNUC__ */
+#endif
 
 /**
  * G_GNUC_DEPRECATED:
@@ -616,7 +677,7 @@
  *
  * Since: 2.2
  */
-#if G_GNUC_CHECK_VERSION(3, 1) || defined(__clang__)
+#if g_macro__has_attribute(__deprecated__)
 #define G_GNUC_DEPRECATED __attribute__((__deprecated__))
 #else
 #define G_GNUC_DEPRECATED
@@ -694,7 +755,7 @@
  *
  * Since: 2.14
  */
-#if G_GNUC_CHECK_VERSION(3, 3)
+#if g_macro__has_attribute(may_alias)
 #define G_GNUC_MAY_ALIAS __attribute__((may_alias))
 #else
 #define G_GNUC_MAY_ALIAS
@@ -718,7 +779,7 @@
  *
  * Since: 2.10
  */
-#if G_GNUC_CHECK_VERSION(3, 4)
+#if g_macro__has_attribute(warn_unused_result)
 #define G_GNUC_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
 #else
 #define G_GNUC_WARN_UNUSED_RESULT


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