diff options
-rw-r--r-- | src/corelib/global/qglobal.cpp | 45 | ||||
-rw-r--r-- | src/corelib/global/qglobal.h | 11 | ||||
-rw-r--r-- | src/corelib/global/qlogging.cpp | 4 | ||||
-rw-r--r-- | src/corelib/global/qlogging.h | 2 |
4 files changed, 55 insertions, 7 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 diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 6362e1b74b..5e58f5a4b0 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -546,11 +546,18 @@ inline void qt_noop(void) {} # define QT_CATCH(A) else # define QT_THROW(A) qt_noop() # define QT_RETHROW qt_noop() +# define QT_TERMINATE_ON_EXCEPTION(expr) do { expr; } while (0) #else # define QT_TRY try # define QT_CATCH(A) catch (A) # define QT_THROW(A) throw A # define QT_RETHROW throw +Q_NORETURN Q_CORE_EXPORT void qTerminate() Q_DECL_NOTHROW; +# ifdef Q_COMPILER_NOEXCEPT +# define QT_TERMINATE_ON_EXCEPTION(expr) do { expr; } while (0) +# else +# define QT_TERMINATE_ON_EXCEPTION(expr) do { try { expr; } catch (...) { qTerminate(); } } while (0) +# endif #endif Q_CORE_EXPORT const char *qVersion(); @@ -593,7 +600,7 @@ Q_CORE_EXPORT QString qt_error_string(int errorCode = -1); #ifndef Q_CC_MSVC Q_NORETURN #endif -Q_CORE_EXPORT void qt_assert(const char *assertion, const char *file, int line); +Q_CORE_EXPORT void qt_assert(const char *assertion, const char *file, int line) Q_DECL_NOTHROW; #if !defined(Q_ASSERT) # if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS) @@ -610,7 +617,7 @@ Q_CORE_EXPORT void qt_assert(const char *assertion, const char *file, int line); #ifndef Q_CC_MSVC Q_NORETURN #endif -Q_CORE_EXPORT void qt_assert_x(const char *where, const char *what, const char *file, int line); +Q_CORE_EXPORT void qt_assert_x(const char *where, const char *what, const char *file, int line) Q_DECL_NOTHROW; #if !defined(Q_ASSERT_X) # if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS) diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp index bb12807f9a..527021381a 100644 --- a/src/corelib/global/qlogging.cpp +++ b/src/corelib/global/qlogging.cpp @@ -240,11 +240,11 @@ QDebug QMessageLogger::critical() #endif #undef qFatal -void QMessageLogger::fatal(const char *msg, ...) +void QMessageLogger::fatal(const char *msg, ...) Q_DECL_NOTHROW { va_list ap; va_start(ap, msg); // use variable arg list - qt_message(QtFatalMsg, context, msg, ap); + QT_TERMINATE_ON_EXCEPTION(qt_message(QtFatalMsg, context, msg, ap)); #ifndef Q_CC_MSVC Q_UNREACHABLE(); #endif diff --git a/src/corelib/global/qlogging.h b/src/corelib/global/qlogging.h index 618c0cd0ea..f1f9643753 100644 --- a/src/corelib/global/qlogging.h +++ b/src/corelib/global/qlogging.h @@ -117,7 +117,7 @@ public: #ifndef Q_CC_MSVC Q_NORETURN #endif - void fatal(const char *msg, ...) + void fatal(const char *msg, ...) Q_DECL_NOTHROW #if defined(Q_CC_GNU) && !defined(__INSURE__) __attribute__ ((format (printf, 2, 3))) #endif |