From e2bd6a6a8f2b9f22e7092578f920e2b3057f4156 Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Fri, 23 Mar 2018 23:10:57 +0530 Subject: [PATCH] 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 #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 --- glib/gmacros.h | 33 ++++++++++++++++++++++++--------- glib/gnulib/verify.h | 10 ++++++---- glib/gtypes.h | 2 +- 3 files changed, 31 insertions(+), 14 deletions(-) diff --git a/glib/gmacros.h b/glib/gmacros.h index 430a3fbb7..fcd49bdcd 100644 --- a/glib/gmacros.h +++ b/glib/gmacros.h @@ -108,21 +108,36 @@ #define G_GNUC_NULL_TERMINATED #endif -/* Clang feature detection: http://clang.llvm.org/docs/LanguageExtensions.html */ -#ifndef __has_attribute -#define __has_attribute(x) 0 +/* + * Clang feature detection: http://clang.llvm.org/docs/LanguageExtensions.html + * 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 -#ifndef __has_feature -#define __has_feature(x) 0 +#ifdef __has_feature +#define g_macro__has_feature __has_feature +#else +#define g_macro__has_feature(x) 0 #endif -#ifndef __has_builtin -#define __has_builtin(x) 0 +#ifdef __has_builtin +#define g_macro__has_builtin __has_builtin +#else +#define g_macro__has_builtin(x) 0 #endif #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_SIZE2(x,y) __attribute__((__alloc_size__(x,y))) #else @@ -223,7 +238,7 @@ #endif /* !__GNUC__ */ #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_NORETURN __attribute__((analyzer_noreturn)) #else diff --git a/glib/gnulib/verify.h b/glib/gnulib/verify.h index 267de2959..f5933b859 100644 --- a/glib/gnulib/verify.h +++ b/glib/gnulib/verify.h @@ -250,21 +250,23 @@ template #define verify(R) _GL_VERIFY (R, "verify (" #R ")") -#ifndef __has_builtin -# define __has_builtin(x) 0 +#ifdef __has_builtin +# define _GL_MACRO__has_builtin __has_builtin +#else +# define _GL_MACRO__has_builtin(x) 0 #endif /* Assume that R always holds. This lets the compiler optimize accordingly. R should not have side-effects; it may or may not be 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__)) # define assume(R) ((R) ? (void) 0 : __builtin_unreachable ()) #elif 1200 <= _MSC_VER # define assume(R) __assume (R) #elif (defined lint \ - && (__has_builtin (__builtin_trap) \ + && (_GL_MACRO__has_builtin (__builtin_trap) \ || 3 < __GNUC__ + (3 < __GNUC_MINOR__ + (4 <= __GNUC_PATCHLEVEL__)))) /* Doing it this way helps various packages when configured with --enable-gcc-warnings, which compiles with -Dlint. It's nicer diff --git a/glib/gtypes.h b/glib/gtypes.h index 047ac6227..09d9bd145 100644 --- a/glib/gtypes.h +++ b/glib/gtypes.h @@ -384,7 +384,7 @@ typedef const gchar * (*GTranslateFunc) (const gchar *str, /* https://bugzilla.gnome.org/show_bug.cgi?id=769104 */ #if __GNUC__ >= 5 && !defined(__INTEL_COMPILER) #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 #endif #endif