diff options
author | Marc Mutz <marc.mutz@kdab.com> | 2012-08-03 10:38:00 +0200 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-08-09 03:26:17 +0200 |
commit | c856e37c5fddec64d8635f3dae57b9cbea1aada4 (patch) | |
tree | 08233d5e1c6ee74811a1ae9e644d8b317c80818b /src/corelib/global/qglobal.cpp | |
parent | 7ef395224ea42a9a8d3469194d960077d7ff21eb (diff) |
Logging: mark qt_assert()/qt_assert_x()/qFatal() as nothrow
These functions are not supposed to return, not even by exception.
qt_message() _can_ throw, but we're fine with the compiler calling
std::terminate() then, since the backtrace will still include the
assertion location.
This behaviour is ensured by a new macro, QT_TERMINATE_ON_EXCEPTION,
which expands to something like
try { expr; } catch(...) { std::terminate(); }
if the compiler doesn't support Q_DECL_NOEXCEPT (but maybe
Q_DECL_NOTHROW), and to something like just
expr;
otherwise (including in the QT_NO_EXCEPTION case).
The real macro preserves scopes in all cases, and aims
to work even if <exception> isn't included in the TU it's used in,
so is a little bit more complex than that.
Change-Id: Ie6a2b7776e6aa77e57bd9aea6e184e5fa1cec81c
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/global/qglobal.cpp')
-rw-r--r-- | src/corelib/global/qglobal.cpp | 45 |
1 files changed, 43 insertions, 2 deletions
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 61ae53b103..17cb9db86f 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -1913,10 +1913,19 @@ void qBadAlloc() QT_THROW(std::bad_alloc()); } +/* \internal + Allows you to call std::terminate() without including <exception>. + Called internally from QT_TERMINATE_ON_EXCEPTION +*/ +Q_NORETURN void qTerminate() Q_DECL_NOTHROW +{ + std::terminate(); +} + /* The Q_ASSERT macro calls this function when the test fails. */ -void qt_assert(const char *assertion, const char *file, int line) +void qt_assert(const char *assertion, const char *file, int line) Q_DECL_NOTHROW { qFatal("ASSERT: \"%s\" in file %s, line %d", assertion, file, line); } @@ -1924,7 +1933,7 @@ void qt_assert(const char *assertion, const char *file, int line) /* The Q_ASSERT_X macro calls this function when the test fails. */ -void qt_assert_x(const char *where, const char *what, const char *file, int line) +void qt_assert_x(const char *where, const char *what, const char *file, int line) Q_DECL_NOTHROW { qFatal("ASSERT failure in %s: \"%s\", file %s, line %d", where, what, file, line); } @@ -3034,6 +3043,38 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters) */ /*! + \macro QT_TERMINATE_ON_EXCEPTION(expr) + \relates <QtGlobal> + \internal + + In general, use of the Q_DECL_NOEXCEPT macro is preferred over + Q_DECL_NOTHROW, because it exhibits well-defined behavior and + supports the more powerful Q_DECL_NOEXCEPT_EXPR variant. However, + use of Q_DECL_NOTHROW has the advantage that Windows builds + benefit on a wide range or compiler versions that do not yet + support the C++11 noexcept feature. + + It may therefore be beneficial to use Q_DECL_NOTHROW and emulate + the C++11 behavior manually with an embedded try/catch. + + Qt provides the QT_TERMINATE_ON_EXCEPTION(expr) macro for this + purpose. It either expands to \c expr (if Qt is compiled without + exception support or the compiler supports C++11 noexcept + semantics) or to + \code + try { expr; } catch(...) { qTerminate(); } + \endocde + otherwise. + + Since this macro expands to just \c expr if the compiler supports + C++11 noexcept, expecting the compiler to take over responsibility + of calling std::terminate() in that case, it should not be used + outside Q_DECL_NOTHROW functions. + + \sa Q_DECL_NOEXCEPT, Q_DECL_NOTHROW, qTerminate() +*/ + +/*! \macro Q_DECL_NOEXCEPT \relates <QtGlobal> \since 5.0 |