gmacros: Don't define bogus __has_* macros

This pollutes the reserved compiler namespace and breaks applications
trying to do their own feature detection. For instance, this falsely
detects that alloca is not a builtin on gcc:

    #include <glib.h>
    #if defined(__has_builtin)
    # if !__has_builtin(alloca)
    #  error "wtf glib?"
    # endif
    #else
    /* version-checking to determine alloca existence */
    #endif

Instead, define our own g_macro__has_* versions that have the
behaviour that we need.

https://bugzilla.gnome.org/show_bug.cgi?id=794635
This commit is contained in:
Nirbheek Chauhan 2018-03-23 23:10:57 +05:30
parent ba4a9538e1
commit e2bd6a6a8f
3 changed files with 31 additions and 14 deletions

View File

@ -108,21 +108,36 @@
#define G_GNUC_NULL_TERMINATED #define G_GNUC_NULL_TERMINATED
#endif #endif
/* Clang feature detection: http://clang.llvm.org/docs/LanguageExtensions.html */ /*
#ifndef __has_attribute * Clang feature detection: http://clang.llvm.org/docs/LanguageExtensions.html
#define __has_attribute(x) 0 * These are not available on GCC, but since the pre-processor doesn't do
* operator short-circuiting, we can't use it in a statement or we'll get:
*
* error: missing binary operator before token "("
*
* 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 #endif
#ifndef __has_feature #ifdef __has_feature
#define __has_feature(x) 0 #define g_macro__has_feature __has_feature
#else
#define g_macro__has_feature(x) 0
#endif #endif
#ifndef __has_builtin #ifdef __has_builtin
#define __has_builtin(x) 0 #define g_macro__has_builtin __has_builtin
#else
#define g_macro__has_builtin(x) 0
#endif #endif
#if (!defined(__clang__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) || \ #if (!defined(__clang__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) || \
(defined(__clang__) && __has_attribute(__alloc_size__)) (defined(__clang__) && g_macro__has_attribute(__alloc_size__))
#define G_GNUC_ALLOC_SIZE(x) __attribute__((__alloc_size__(x))) #define G_GNUC_ALLOC_SIZE(x) __attribute__((__alloc_size__(x)))
#define G_GNUC_ALLOC_SIZE2(x,y) __attribute__((__alloc_size__(x,y))) #define G_GNUC_ALLOC_SIZE2(x,y) __attribute__((__alloc_size__(x,y)))
#else #else
@ -223,7 +238,7 @@
#endif /* !__GNUC__ */ #endif /* !__GNUC__ */
#endif /* !G_DISABLE_DEPRECATED */ #endif /* !G_DISABLE_DEPRECATED */
#if __has_feature(attribute_analyzer_noreturn) && defined(__clang_analyzer__) #if g_macro__has_feature(attribute_analyzer_noreturn) && defined(__clang_analyzer__)
#define G_ANALYZER_ANALYZING 1 #define G_ANALYZER_ANALYZING 1
#define G_ANALYZER_NORETURN __attribute__((analyzer_noreturn)) #define G_ANALYZER_NORETURN __attribute__((analyzer_noreturn))
#else #else

View File

@ -250,21 +250,23 @@ template <int w>
#define verify(R) _GL_VERIFY (R, "verify (" #R ")") #define verify(R) _GL_VERIFY (R, "verify (" #R ")")
#ifndef __has_builtin #ifdef __has_builtin
# define __has_builtin(x) 0 # define _GL_MACRO__has_builtin __has_builtin
#else
# define _GL_MACRO__has_builtin(x) 0
#endif #endif
/* Assume that R always holds. This lets the compiler optimize /* Assume that R always holds. This lets the compiler optimize
accordingly. R should not have side-effects; it may or may not be accordingly. R should not have side-effects; it may or may not be
evaluated. Behavior is undefined if R is false. */ evaluated. Behavior is undefined if R is false. */
#if (__has_builtin (__builtin_unreachable) \ #if (_GL_MACRO__has_builtin (__builtin_unreachable) \
|| 4 < __GNUC__ + (5 <= __GNUC_MINOR__)) || 4 < __GNUC__ + (5 <= __GNUC_MINOR__))
# define assume(R) ((R) ? (void) 0 : __builtin_unreachable ()) # define assume(R) ((R) ? (void) 0 : __builtin_unreachable ())
#elif 1200 <= _MSC_VER #elif 1200 <= _MSC_VER
# define assume(R) __assume (R) # define assume(R) __assume (R)
#elif (defined lint \ #elif (defined lint \
&& (__has_builtin (__builtin_trap) \ && (_GL_MACRO__has_builtin (__builtin_trap) \
|| 3 < __GNUC__ + (3 < __GNUC_MINOR__ + (4 <= __GNUC_PATCHLEVEL__)))) || 3 < __GNUC__ + (3 < __GNUC_MINOR__ + (4 <= __GNUC_PATCHLEVEL__))))
/* Doing it this way helps various packages when configured with /* Doing it this way helps various packages when configured with
--enable-gcc-warnings, which compiles with -Dlint. It's nicer --enable-gcc-warnings, which compiles with -Dlint. It's nicer

View File

@ -384,7 +384,7 @@ typedef const gchar * (*GTranslateFunc) (const gchar *str,
/* https://bugzilla.gnome.org/show_bug.cgi?id=769104 */ /* https://bugzilla.gnome.org/show_bug.cgi?id=769104 */
#if __GNUC__ >= 5 && !defined(__INTEL_COMPILER) #if __GNUC__ >= 5 && !defined(__INTEL_COMPILER)
#define _GLIB_HAVE_BUILTIN_OVERFLOW_CHECKS #define _GLIB_HAVE_BUILTIN_OVERFLOW_CHECKS
#elif __has_builtin(__builtin_uadd_overflow) #elif g_macro__has_builtin(__builtin_uadd_overflow)
#define _GLIB_HAVE_BUILTIN_OVERFLOW_CHECKS #define _GLIB_HAVE_BUILTIN_OVERFLOW_CHECKS
#endif #endif
#endif #endif