summaryrefslogtreecommitdiffstats
path: root/src/corelib/global/qassert.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/global/qassert.cpp')
-rw-r--r--src/corelib/global/qassert.cpp112
1 files changed, 94 insertions, 18 deletions
diff --git a/src/corelib/global/qassert.cpp b/src/corelib/global/qassert.cpp
index 2e340ebbb2..6a29cbfa21 100644
--- a/src/corelib/global/qassert.cpp
+++ b/src/corelib/global/qassert.cpp
@@ -5,14 +5,51 @@
#include <QtCore/qlogging.h>
+#include <cstdlib>
#include <cstdio>
#include <exception>
#ifndef QT_NO_EXCEPTIONS
#include <new>
#endif
+#if defined(Q_CC_MSVC)
+# include <crtdbg.h>
+#endif
+#ifdef Q_OS_WIN
+# include <qt_windows.h>
+#endif
+
QT_BEGIN_NAMESPACE
+void qAbort()
+{
+#ifdef Q_OS_WIN
+ // std::abort() in the MSVC runtime will call _exit(3) if the abort
+ // behavior is _WRITE_ABORT_MSG - see also _set_abort_behavior(). This is
+ // the default for a debug-mode build of the runtime. Worse, MinGW's
+ // std::abort() implementation (in msvcrt.dll) is basically a call to
+ // _exit(3) too. Unfortunately, _exit() and _Exit() *do* run the static
+ // destructors of objects in DLLs, a violation of the C++ standard (see
+ // [support.start.term]). So we bypass std::abort() and directly
+ // terminate the application.
+
+# if defined(Q_CC_MSVC)
+ if (IsProcessorFeaturePresent(PF_FASTFAIL_AVAILABLE))
+ __fastfail(FAST_FAIL_FATAL_APP_EXIT);
+# else
+ RaiseFailFastException(nullptr, nullptr, 0);
+# endif
+
+ // Fallback
+ TerminateProcess(GetCurrentProcess(), STATUS_FATAL_APP_EXIT);
+
+ // Tell the compiler the application has stopped.
+ Q_UNREACHABLE_IMPL();
+#else // !Q_OS_WIN
+ std::abort();
+#endif
+}
+
/*!
\macro void Q_ASSERT(bool test)
\relates <QtAssert>
@@ -139,31 +176,52 @@ void qBadAlloc()
/*!
\macro void Q_ASSUME(bool expr)
+ \deprecated
\relates <QtAssert>
\since 5.0
- Causes the compiler to assume that \a expr is \c true. This macro is useful
- for improving code generation, by providing the compiler with hints about
- conditions that it would not otherwise know about. However, there is no
- guarantee that the compiler will actually use those hints.
+ Causes the compiler to assume that \a expr is \c true.
- This macro could be considered a "lighter" version of \l{Q_ASSERT()}. While
- Q_ASSERT will abort the program's execution if the condition is \c false,
- Q_ASSUME will tell the compiler not to generate code for those conditions.
- Therefore, it is important that the assumptions always hold, otherwise
- undefined behavior may occur.
+ This macro is known to produce worse code than when no assumption was
+ inserted in the code, with some compiler versions. The arguments passed to
+ it are always evaluated, even in release mode, with some compilers and not
+ others, so application code needs to be aware of those possible differences
+ in behavior.
- If \a expr is a constantly \c false condition, Q_ASSUME will tell the compiler
- that the current code execution cannot be reached. That is, Q_ASSUME(false)
- is equivalent to Q_UNREACHABLE().
+ Do not use it in new code. It is retained as-is for compatibility with old
+ code and will likely be removed in the next major version Qt.
- In debug builds the condition is enforced by an assert to facilitate debugging.
+ \sa Q_ASSERT(), Q_UNREACHABLE(), Q_LIKELY()
+*/
- \note Q_LIKELY() tells the compiler that the expression is likely, but not
- the only possibility. Q_ASSUME tells the compiler that it is the only
- possibility.
+/*!
+ \macro QT_TERMINATE_ON_EXCEPTION(expr)
+ \relates <QtGlobal>
+ \internal
- \sa Q_ASSERT(), Q_UNREACHABLE(), Q_LIKELY()
+ 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
+ \snippet code/src_corelib_global_qglobal.cpp qterminate
+ 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()
*/
/*!
@@ -195,7 +253,25 @@ void qBadAlloc()
In debug builds the condition is enforced by an assert to facilitate debugging.
- \sa Q_ASSERT(), Q_ASSUME(), qFatal()
+ \note Use the macro Q_UNREACHABLE_RETURN() to insert return statements for
+ compilers that need them, without causing warnings for compilers that
+ complain about its presence.
+
+ \sa Q_ASSERT(), qFatal(), Q_UNREACHABLE_RETURN()
*/
+/*!
+ \macro void Q_UNREACHABLE_RETURN(...)
+ \relates <QtAssert>
+ \since 6.5
+
+ This is equivalent to
+ \code
+ Q_UNREACHABLE();
+ return __VA_ARGS__;
+ \endcode
+ except it omits the return on compilers that would warn about it.
+
+ \sa Q_UNREACHABLE()
+*/
QT_END_NAMESPACE