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.cpp277
1 files changed, 277 insertions, 0 deletions
diff --git a/src/corelib/global/qassert.cpp b/src/corelib/global/qassert.cpp
new file mode 100644
index 0000000000..6a29cbfa21
--- /dev/null
+++ b/src/corelib/global/qassert.cpp
@@ -0,0 +1,277 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qassert.h"
+
+#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>
+
+ Prints a warning message containing the source code file name and
+ line number if \a test is \c false.
+
+ Q_ASSERT() is useful for testing pre- and post-conditions
+ during development. It does nothing if \c QT_NO_DEBUG was defined
+ during compilation.
+
+ Example:
+
+ \snippet code/src_corelib_global_qglobal.cpp 17
+
+ If \c b is zero, the Q_ASSERT statement will output the following
+ message using the qFatal() function:
+
+ \snippet code/src_corelib_global_qglobal.cpp 18
+
+ \sa Q_ASSERT_X(), qFatal(), {Debugging Techniques}
+*/
+
+/*!
+ \macro void Q_ASSERT_X(bool test, const char *where, const char *what)
+ \relates <QtAssert>
+
+ Prints the message \a what together with the location \a where,
+ the source file name and line number if \a test is \c false.
+
+ Q_ASSERT_X is useful for testing pre- and post-conditions during
+ development. It does nothing if \c QT_NO_DEBUG was defined during
+ compilation.
+
+ Example:
+
+ \snippet code/src_corelib_global_qglobal.cpp 19
+
+ If \c b is zero, the Q_ASSERT_X statement will output the following
+ message using the qFatal() function:
+
+ \snippet code/src_corelib_global_qglobal.cpp 20
+
+ \sa Q_ASSERT(), qFatal(), {Debugging Techniques}
+*/
+
+/*
+ The Q_ASSERT macro calls this function when the test fails.
+*/
+void qt_assert(const char *assertion, const char *file, int line) noexcept
+{
+ QMessageLogger(file, line, nullptr)
+ .fatal("ASSERT: \"%s\" in file %s, line %d", assertion, file, 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) noexcept
+{
+ QMessageLogger(file, line, nullptr)
+ .fatal("ASSERT failure in %s: \"%s\", file %s, line %d", where, what, file, line);
+}
+
+/*!
+ \macro void Q_CHECK_PTR(void *pointer)
+ \relates <QtAssert>
+
+ If \a pointer is \nullptr, prints a message containing the source
+ code's file name and line number, saying that the program ran out
+ of memory and aborts program execution. It throws \c std::bad_alloc instead
+ if exceptions are enabled.
+
+ Q_CHECK_PTR does nothing if \c QT_NO_DEBUG and \c QT_NO_EXCEPTIONS were
+ defined during compilation. Therefore you must not use Q_CHECK_PTR to check
+ for successful memory allocations because the check will be disabled in
+ some cases.
+
+ Example:
+
+ \snippet code/src_corelib_global_qglobal.cpp 21
+
+ \sa qWarning(), {Debugging Techniques}
+*/
+
+/*!
+ \fn template <typename T> T *q_check_ptr(T *p)
+ \relates <QtAssert>
+
+ Uses Q_CHECK_PTR on \a p, then returns \a p.
+
+ This can be used as an inline version of Q_CHECK_PTR.
+*/
+
+/*!
+ \internal
+ The Q_CHECK_PTR macro calls this function if an allocation check
+ fails.
+*/
+void qt_check_pointer(const char *n, int l) noexcept
+{
+ // make separate printing calls so that the first one may flush;
+ // the second one could want to allocate memory (fputs prints a
+ // newline and stderr auto-flushes).
+ fputs("Out of memory", stderr);
+ fprintf(stderr, " in %s, line %d\n", n, l);
+
+ std::terminate();
+}
+
+/*
+ \internal
+ Allows you to throw an exception without including <new>
+ Called internally from Q_CHECK_PTR on certain OS combinations
+*/
+void qBadAlloc()
+{
+#ifndef QT_NO_EXCEPTIONS
+ throw std::bad_alloc();
+#else
+ std::terminate();
+#endif
+}
+
+/*!
+ \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 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.
+
+ 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.
+
+ \sa Q_ASSERT(), Q_UNREACHABLE(), Q_LIKELY()
+*/
+
+/*!
+ \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
+ \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()
+*/
+
+/*!
+ \macro void Q_UNREACHABLE()
+ \relates <QtAssert>
+ \since 5.0
+
+ Tells the compiler that the current point cannot be reached by any
+ execution, so it may optimize any code paths leading here as dead code, as
+ well as code continuing from here.
+
+ This macro is useful to mark impossible conditions. For example, given the
+ following enum:
+
+ \snippet code/src_corelib_global_qglobal.cpp qunreachable-enum
+
+ One can write a switch table like so:
+
+ \snippet code/src_corelib_global_qglobal.cpp qunreachable-switch
+
+ The advantage of inserting Q_UNREACHABLE() at that point is that the
+ compiler is told not to generate code for a shape variable containing that
+ value. If the macro is missing, the compiler will still generate the
+ necessary comparisons for that value. If the case label were removed, some
+ compilers could produce a warning that some enum values were not checked.
+
+ By using this macro in impossible conditions, code coverage may be improved
+ as dead code paths may be eliminated.
+
+ In debug builds the condition is enforced by an assert to facilitate debugging.
+
+ \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