Add the QT_HAS_xxx macros for post-C++11 feature testing

And for compiler extensions. QT_HAS_BUILTIN and QT_HAS_ATTRIBUTE will
come in handy.

Change-Id: I255870833a024a36adf6ffff13ecf06624bfc1ef
Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
This commit is contained in:
Thiago Macieira 2015-07-01 14:38:22 -07:00
parent 3d52b05a63
commit 6f298be076
4 changed files with 39 additions and 24 deletions

View File

@ -1109,6 +1109,37 @@
# define Q_DECL_CONST_FUNCTION Q_DECL_PURE_FUNCTION # define Q_DECL_CONST_FUNCTION Q_DECL_PURE_FUNCTION
#endif #endif
/*
* SG10's SD-6 feature detection and some useful extensions from Clang and GCC
* https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations
* http://clang.llvm.org/docs/LanguageExtensions.html#feature-checking-macros
*/
#ifdef __has_builtin
# define QT_HAS_BUILTIN(x) __has_builtin(x)
#else
# define QT_HAS_BUILTIN(x) 0
#endif
#ifdef __has_attribute
# define QT_HAS_ATTRIBUTE(x) __has_attribute(x)
#else
# define QT_HAS_ATTRIBUTE(x) 0
#endif
#ifdef __has_cpp_attribute
# define QT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
#else
# define QT_HAS_CPP_ATTRIBUTE(x) 0
#endif
#ifdef __has_include
# define QT_HAS_INCLUDE(x) __has_include(x)
#else
# define QT_HAS_INCLUDE(x) 0
#endif
#ifdef __has_include_next
# define QT_HAS_INCLUDE_NEXT(x) __has_include_next(x)
#else
# define QT_HAS_INCLUDE_NEXT(x) 0
#endif
/* /*
* Warning/diagnostic handling * Warning/diagnostic handling
*/ */

View File

@ -87,12 +87,6 @@ template <typename T> inline T qFromUnaligned(const uchar *src)
*/ */
template <typename T> T qbswap(T source); template <typename T> T qbswap(T source);
#ifdef __has_builtin
# define QT_HAS_BUILTIN(x) __has_builtin(x)
#else
# define QT_HAS_BUILTIN(x) 0
#endif
// GCC 4.3 implemented all the intrinsics, but the 16-bit one only got implemented in 4.8; // GCC 4.3 implemented all the intrinsics, but the 16-bit one only got implemented in 4.8;
// Clang 2.6 implemented the 32- and 64-bit but waited until 3.2 to implement the 16-bit one // Clang 2.6 implemented the 32- and 64-bit but waited until 3.2 to implement the 16-bit one
#if (defined(Q_CC_GNU) && Q_CC_GNU >= 403) || QT_HAS_BUILTIN(__builtin_bswap32) #if (defined(Q_CC_GNU) && Q_CC_GNU >= 403) || QT_HAS_BUILTIN(__builtin_bswap32)
@ -154,8 +148,6 @@ template <> inline quint16 qbswap<quint16>(quint16 source)
} }
#endif // GCC & Clang intrinsics #endif // GCC & Clang intrinsics
#undef QT_HAS_BUILTIN
// signed specializations // signed specializations
template <> inline qint64 qbswap<qint64>(qint64 source) template <> inline qint64 qbswap<qint64>(qint64 source)
{ {

View File

@ -75,17 +75,13 @@
# include "private/qcore_unix_p.h" # include "private/qcore_unix_p.h"
#endif #endif
#ifndef __has_include
# define __has_include(x) 0
#endif
#ifndef QT_BOOTSTRAPPED #ifndef QT_BOOTSTRAPPED
#if !defined QT_NO_REGULAREXPRESSION #if !defined QT_NO_REGULAREXPRESSION
# ifdef __UCLIBC__ # ifdef __UCLIBC__
# if __UCLIBC_HAS_BACKTRACE__ # if __UCLIBC_HAS_BACKTRACE__
# define QLOGGING_HAVE_BACKTRACE # define QLOGGING_HAVE_BACKTRACE
# endif # endif
# elif (defined(__GLIBC__) && defined(__GLIBCXX__)) || (__has_include(<cxxabi.h>) && __has_include(<execinfo.h>)) # elif (defined(__GLIBC__) && defined(__GLIBCXX__)) || (QT_HAS_INCLUDE(<cxxabi.h>) && QT_HAS_INCLUDE(<execinfo.h>))
# define QLOGGING_HAVE_BACKTRACE # define QLOGGING_HAVE_BACKTRACE
# endif # endif
#endif #endif
@ -94,7 +90,7 @@
extern char *__progname; extern char *__progname;
#endif #endif
#if defined(Q_OS_LINUX) && (defined(__GLIBC__) || __has_include(<sys/syscall.h>)) #if defined(Q_OS_LINUX) && (defined(__GLIBC__) || QT_HAS_INCLUDE(<sys/syscall.h>))
# include <sys/syscall.h> # include <sys/syscall.h>
static long qt_gettid() static long qt_gettid()
{ {

View File

@ -56,10 +56,6 @@
# include <immintrin.h> // for _addcarry_u<nn> # include <immintrin.h> // for _addcarry_u<nn>
#endif #endif
#ifndef __has_builtin
# define __has_builtin(x) 0
#endif
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
#if !defined(Q_CC_MIPS) #if !defined(Q_CC_MIPS)
@ -230,28 +226,28 @@ mul_overflow(T v1, T v2, T *r)
#endif #endif
// GCC 5 and Clang have builtins to detect overflows // GCC 5 and Clang have builtins to detect overflows
#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || __has_builtin(__builtin_uadd_overflow) #if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_uadd_overflow)
template <> inline bool add_overflow(unsigned v1, unsigned v2, unsigned *r) template <> inline bool add_overflow(unsigned v1, unsigned v2, unsigned *r)
{ return __builtin_uadd_overflow(v1, v2, r); } { return __builtin_uadd_overflow(v1, v2, r); }
#endif #endif
#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || __has_builtin(__builtin_uaddl_overflow) #if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_uaddl_overflow)
template <> inline bool add_overflow(unsigned long v1, unsigned long v2, unsigned long *r) template <> inline bool add_overflow(unsigned long v1, unsigned long v2, unsigned long *r)
{ return __builtin_uaddl_overflow(v1, v2, r); } { return __builtin_uaddl_overflow(v1, v2, r); }
#endif #endif
#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || __has_builtin(__builtin_uaddll_overflow) #if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_uaddll_overflow)
template <> inline bool add_overflow(unsigned long long v1, unsigned long long v2, unsigned long long *r) template <> inline bool add_overflow(unsigned long long v1, unsigned long long v2, unsigned long long *r)
{ return __builtin_uaddll_overflow(v1, v2, r); } { return __builtin_uaddll_overflow(v1, v2, r); }
#endif #endif
#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || __has_builtin(__builtin_umul_overflow) #if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_umul_overflow)
template <> inline bool mul_overflow(unsigned v1, unsigned v2, unsigned *r) template <> inline bool mul_overflow(unsigned v1, unsigned v2, unsigned *r)
{ return __builtin_umul_overflow(v1, v2, r); } { return __builtin_umul_overflow(v1, v2, r); }
#endif #endif
#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || __has_builtin(__builtin_umull_overflow) #if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_umull_overflow)
template <> inline bool mul_overflow(unsigned long v1, unsigned long v2, unsigned long *r) template <> inline bool mul_overflow(unsigned long v1, unsigned long v2, unsigned long *r)
{ return __builtin_umull_overflow(v1, v2, r); } { return __builtin_umull_overflow(v1, v2, r); }
#endif #endif
#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || __has_builtin(__builtin_umulll_overflow) #if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_umulll_overflow)
template <> inline bool mul_overflow(unsigned long long v1, unsigned long long v2, unsigned long long *r) template <> inline bool mul_overflow(unsigned long long v1, unsigned long long v2, unsigned long long *r)
{ return __builtin_umulll_overflow(v1, v2, r); } { return __builtin_umulll_overflow(v1, v2, r); }
# define HAVE_MUL64_OVERFLOW # define HAVE_MUL64_OVERFLOW