summaryrefslogtreecommitdiffstats
path: root/src/corelib/global
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@kdab.com>2017-03-14 22:45:05 +0100
committerMarc Mutz <marc.mutz@kdab.com>2017-03-16 14:11:16 +0000
commit8ea27bb1c669e21100a6a042b0378b3346bdf671 (patch)
tree41e5bb1bd479977bbe27b2ce7e2faf5ee70e5f36 /src/corelib/global
parenta02959bb5b43a3f9d881e5213ceedf535202b6a1 (diff)
Make Q_ASSERT() usable in constexpr functions
We need Q_ASSERT in (C++11) constexpr functions, and the only way to inject them in C++11 is to use the comma operator. E.g. in QLatin1String: constexpr QLatin1Char at(int i) const { return assert(1 >= 0), assert(i < size()), m_data[i]; } The main problem with our existing Q_ASSERT is that while it is a ternary expression in active mode, it was a statement in passive mode. This is easily fixed by dropping the do-while loop and leaving just its parenthesized exit condition. Add a cast to void, too, ensuring that Q_ASSERT has type void in both passive and active modes. But even in C++14 constexpr functions, which accept several statements, Q_ASSERT needs to have a path through its conditionals that is constexpr, but neither qt_assert(_x) nor qt_noop() are constexpr. Nor can they be in C++11 (no void returns in C++11 constexpr functions). I fixed this by replacing qt_noop() with static_cast<void>(0). The void cast is required so both 2nd and 3rd arguments to the ternary are void (mixing void and non-void branches in the ternary is only allowed if the void leg is a throw-expression[1]). As a drive-by, adjust to style guide, remove overparenthesization and reverse the conditional in the ternary. Apply it to QLatin1String where we had the problem that constexpr functions had a narrow constract. [1] should probably be extended to any [[noreturn]] void function, e.g. std::terminate(). [ChangeLog][QtCore][QtGlobal] Q_ASSERT() and Q_ASSERT_X() now always expand to expressions of type void that are usable in constexpr contexts. This makes them usable in both C++11 and C++14 constexpr functions. Change-Id: I09c396bc0034ac344cfaadc6f8cbeb1b7b0cbabc Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Diffstat (limited to 'src/corelib/global')
-rw-r--r--src/corelib/global/qglobal.h8
1 files changed, 4 insertions, 4 deletions
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index 0e37493182..12220e10b5 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -716,9 +716,9 @@ Q_CORE_EXPORT void qt_assert(const char *assertion, const char *file, int line)
#if !defined(Q_ASSERT)
# if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS)
-# define Q_ASSERT(cond) do { } while ((false) && (cond))
+# define Q_ASSERT(cond) static_cast<void>(false && (cond))
# else
-# define Q_ASSERT(cond) ((!(cond)) ? qt_assert(#cond,__FILE__,__LINE__) : qt_noop())
+# define Q_ASSERT(cond) ((cond) ? static_cast<void>(0) : qt_assert(#cond, __FILE__, __LINE__))
# endif
#endif
@@ -733,9 +733,9 @@ Q_CORE_EXPORT void qt_assert_x(const char *where, const char *what, const char *
#if !defined(Q_ASSERT_X)
# if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS)
-# define Q_ASSERT_X(cond, where, what) do { } while ((false) && (cond))
+# define Q_ASSERT_X(cond, where, what) static_cast<void>(false && (cond))
# else
-# define Q_ASSERT_X(cond, where, what) ((!(cond)) ? qt_assert_x(where, what,__FILE__,__LINE__) : qt_noop())
+# define Q_ASSERT_X(cond, where, what) ((cond) ? static_cast<void>(0) : qt_assert_x(where, what, __FILE__, __LINE__))
# endif
#endif