diff --git a/Include/internal/pycore_bitutils.h b/Include/internal/pycore_bitutils.h index 0bd3270fe82e5c..006bbef422cce5 100644 --- a/Include/internal/pycore_bitutils.h +++ b/Include/internal/pycore_bitutils.h @@ -17,9 +17,8 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -#if defined(__clang__) || \ - (defined(__GNUC__) && \ - ((__GNUC__ >= 5) || (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8))) +#if (defined(__GNUC__) \ + && ((__GNUC__ >= 5) || (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8))) /* __builtin_bswap16() is available since GCC 4.8, __builtin_bswap32() is available since GCC 4.3, __builtin_bswap64() is available since GCC 4.3. */ @@ -34,7 +33,8 @@ extern "C" { static inline uint16_t _Py_bswap16(uint16_t word) { -#ifdef _PY_HAVE_BUILTIN_BSWAP + // bpo-41617: __builtin_bswap16() is not available in clang 3.0 and older. +#if _Py_has_builtin(__builtin_bswap16) || defined(_PY_HAVE_BUILTIN_BSWAP) return __builtin_bswap16(word); #elif defined(_MSC_VER) Py_BUILD_ASSERT(sizeof(word) == sizeof(unsigned short)); @@ -49,7 +49,7 @@ _Py_bswap16(uint16_t word) static inline uint32_t _Py_bswap32(uint32_t word) { -#ifdef _PY_HAVE_BUILTIN_BSWAP +#if _Py_has_builtin(__builtin_bswap32) || defined(_PY_HAVE_BUILTIN_BSWAP) return __builtin_bswap32(word); #elif defined(_MSC_VER) Py_BUILD_ASSERT(sizeof(word) == sizeof(unsigned long)); @@ -66,7 +66,7 @@ _Py_bswap32(uint32_t word) static inline uint64_t _Py_bswap64(uint64_t word) { -#ifdef _PY_HAVE_BUILTIN_BSWAP +#if _Py_has_builtin(__builtin_bswap64) || defined(_PY_HAVE_BUILTIN_BSWAP) return __builtin_bswap64(word); #elif defined(_MSC_VER) return _byteswap_uint64(word); diff --git a/Include/pymacro.h b/Include/pymacro.h index 856cae774d61c7..4cd811070d7701 100644 --- a/Include/pymacro.h +++ b/Include/pymacro.h @@ -127,4 +127,19 @@ Py_FatalError("Unreachable C code path reached") #endif + +// Test if the compiler has the specified builtin function. +// +// __has_builtin() is used if the compiler provides it. +// Otherwise, always return 0. +// For example, clang and GCC 10 provide __has_builtin(). +// +// _Py_has_builtin() should not be used to detect support for a builtin macro; +// use #ifdef instead. +#ifdef __has_builtin +# define _Py_has_builtin(x) __has_builtin(x) +#else +# define _Py_has_builtin(x) 0 +#endif + #endif /* Py_PYMACRO_H */ diff --git a/Misc/NEWS.d/next/Build/2020-08-24-18-34-01.bpo-41617.sKKXz7.rst b/Misc/NEWS.d/next/Build/2020-08-24-18-34-01.bpo-41617.sKKXz7.rst new file mode 100644 index 00000000000000..715eadbee896f1 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2020-08-24-18-34-01.bpo-41617.sKKXz7.rst @@ -0,0 +1,2 @@ +Fix ``pycore_bitutils.h`` header file to support old clang versions: +``__builtin_bswap16()`` is not available in LLVM clang 3.0.