summaryrefslogtreecommitdiffstats
path: root/src/corelib/global
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2017-11-05 17:54:35 -0800
committerThiago Macieira <thiago.macieira@intel.com>2017-11-21 20:01:18 +0000
commit0ac2dca977ecc4020f51af57908a2640d00bcd9e (patch)
treebe399d18dc57bef0d1dad21affd6ec2c31e94132 /src/corelib/global
parentef7c0594bf9e41813c9c841e00c3a52269d363f5 (diff)
Add support for C11 static_assert and thread_local
Tested with Clang, GCC 4.5 & up, ICC 17 and MSVC 2017. No current version of MSVC supports C11 and GCC implemented the features slightly later in C than in C++. Change-Id: I57a1bd6e0c194530b732fffd14f45c5074c9a052 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io> Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
Diffstat (limited to 'src/corelib/global')
-rw-r--r--src/corelib/global/qcompilerdetection.h29
-rw-r--r--src/corelib/global/qglobal.h53
2 files changed, 56 insertions, 26 deletions
diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h
index 2c58ff87e9..e4b756f4b7 100644
--- a/src/corelib/global/qcompilerdetection.h
+++ b/src/corelib/global/qcompilerdetection.h
@@ -651,6 +651,12 @@
# undef Q_COMPILER_CONSTEXPR
# endif
# endif
+# elif defined(__STDC_VERSION__) && __STDC_VERSION__ > 199901L s
+// C11 features supported. Only tested with ICC 17 and up.
+# define Q_COMPILER_STATIC_ASSERT
+# if __has_include(<threads.h>)
+# define Q_COMPILER_THREAD_LOCAL
+# endif
# endif
#endif
@@ -803,6 +809,17 @@
# endif
# endif
+# if defined(__STDC_VERSION__)
+# if __has_feature(c_static_assert)
+# define Q_COMPILER_STATIC_ASSERT
+# endif
+# if __has_feature(c_thread_local) && __has_include(<threads.h>)
+# if !defined(__FreeBSD__) /* FreeBSD clang fails on __cxa_thread_atexit */
+# define Q_COMPILER_THREAD_LOCAL
+# endif
+# endif
+# endif
+
# if defined(__has_warning)
# if __has_warning("-Wunused-private-field")
# define Q_DECL_UNUSED_MEMBER Q_DECL_UNUSED
@@ -898,6 +915,18 @@
# define Q_COMPILER_RETURN_TYPE_DEDUCTION
# endif
# endif
+# if defined(__STDC_VERSION__) && __STDC_VERSION__ > 199901L
+# if Q_CC_GNU >= 407
+ /* C11 features supported in GCC 4.7: */
+# define Q_COMPILER_STATIC_ASSERT
+# endif
+# if Q_CC_GNU >= 409
+ /* C11 features supported in GCC 4.9: */
+# if __has_include(<threads.h>)
+# define Q_COMPILER_THREAD_LOCAL
+# endif
+# endif
+# endif
#endif
#if defined(Q_CC_MSVC)
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index e49bace002..33b86a7321 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -47,6 +47,7 @@
# include <utility>
#endif
#ifndef __ASSEMBLER__
+# include <assert.h>
# include <stddef.h>
#endif
@@ -105,6 +106,32 @@
# define Q_OF_MACH_O
#endif
+/*
+ Avoid "unused parameter" warnings
+*/
+#define Q_UNUSED(x) (void)x;
+
+#if defined(__cplusplus) && defined(Q_COMPILER_STATIC_ASSERT)
+# define Q_STATIC_ASSERT(Condition) static_assert(bool(Condition), #Condition)
+# define Q_STATIC_ASSERT_X(Condition, Message) static_assert(bool(Condition), Message)
+#elif defined(Q_COMPILER_STATIC_ASSERT)
+// C11 mode - using the _S version in case <assert.h> doesn't do the right thing
+# define Q_STATIC_ASSERT(Condition) _Static_assert(!!(Condition), #Condition)
+# define Q_STATIC_ASSERT_X(Condition, Message) _Static_assert(!!(Condition), Message)
+#else
+// C89 & C99 version
+# define Q_STATIC_ASSERT_PRIVATE_JOIN(A, B) Q_STATIC_ASSERT_PRIVATE_JOIN_IMPL(A, B)
+# define Q_STATIC_ASSERT_PRIVATE_JOIN_IMPL(A, B) A ## B
+# ifdef __COUNTER__
+# define Q_STATIC_ASSERT(Condition) \
+ typedef char Q_STATIC_ASSERT_PRIVATE_JOIN(q_static_assert_result, __COUNTER__) [(Condition) ? 1 : -1];
+# else
+# define Q_STATIC_ASSERT(Condition) \
+ typedef char Q_STATIC_ASSERT_PRIVATE_JOIN(q_static_assert_result, __LINE__) [(Condition) ? 1 : -1];
+# endif /* __COUNTER__ */
+# define Q_STATIC_ASSERT_X(Condition, Message) Q_STATIC_ASSERT(Condition)
+#endif
+
#ifdef __cplusplus
#include <algorithm>
@@ -688,11 +715,6 @@ Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qSharedBuild() Q_DECL_NOTHROW;
#endif
/*
- Avoid "unused parameter" warnings
-*/
-#define Q_UNUSED(x) (void)x;
-
-/*
Debugging and error handling
*/
@@ -750,27 +772,6 @@ Q_CORE_EXPORT void qt_assert_x(const char *where, const char *what, const char *
# endif
#endif
-
-#ifdef Q_COMPILER_STATIC_ASSERT
-#define Q_STATIC_ASSERT(Condition) static_assert(bool(Condition), #Condition)
-#define Q_STATIC_ASSERT_X(Condition, Message) static_assert(bool(Condition), Message)
-#else
-// Intentionally undefined
-template <bool Test> class QStaticAssertFailure;
-template <> class QStaticAssertFailure<true> {};
-
-#define Q_STATIC_ASSERT_PRIVATE_JOIN(A, B) Q_STATIC_ASSERT_PRIVATE_JOIN_IMPL(A, B)
-#define Q_STATIC_ASSERT_PRIVATE_JOIN_IMPL(A, B) A ## B
-#ifdef __COUNTER__
-#define Q_STATIC_ASSERT(Condition) \
- enum {Q_STATIC_ASSERT_PRIVATE_JOIN(q_static_assert_result, __COUNTER__) = sizeof(QStaticAssertFailure<!!(Condition)>)}
-#else
-#define Q_STATIC_ASSERT(Condition) \
- enum {Q_STATIC_ASSERT_PRIVATE_JOIN(q_static_assert_result, __LINE__) = sizeof(QStaticAssertFailure<!!(Condition)>)}
-#endif /* __COUNTER__ */
-#define Q_STATIC_ASSERT_X(Condition, Message) Q_STATIC_ASSERT(Condition)
-#endif
-
Q_NORETURN Q_CORE_EXPORT void qt_check_pointer(const char *, int) Q_DECL_NOTHROW;
Q_CORE_EXPORT void qBadAlloc();