diff --git a/src/corelib/global/qassert.cpp b/src/corelib/global/qassert.cpp index 5e0a366cf2e..758c11cc570 100644 --- a/src/corelib/global/qassert.cpp +++ b/src/corelib/global/qassert.cpp @@ -137,4 +137,65 @@ void qBadAlloc() #endif } +/*! + \macro void Q_ASSUME(bool expr) + \relates + \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. + + 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. + + 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(). + + In debug builds the condition is enforced by an assert to facilitate debugging. + + \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. + + \sa Q_ASSERT(), Q_UNREACHABLE(), Q_LIKELY() +*/ + +/*! + \macro void Q_UNREACHABLE() + \relates + \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. + + \sa Q_ASSERT(), Q_ASSUME(), qFatal() +*/ + QT_END_NAMESPACE diff --git a/src/corelib/global/qassert.h b/src/corelib/global/qassert.h index 20acb00c7cf..c3696d10a88 100644 --- a/src/corelib/global/qassert.h +++ b/src/corelib/global/qassert.h @@ -60,6 +60,19 @@ Q_CORE_EXPORT void qBadAlloc(); template inline T *q_check_ptr(T *p) { Q_CHECK_PTR(p); return p; } +// Q_UNREACHABLE_IMPL() and Q_ASSUME_IMPL() used below are defined in qcompilerdetection.h +#define Q_UNREACHABLE() \ + do {\ + Q_ASSERT_X(false, "Q_UNREACHABLE()", "Q_UNREACHABLE was reached");\ + Q_UNREACHABLE_IMPL();\ + } while (false) + +#define Q_ASSUME(Expr) \ + [] (bool valueOfExpression) {\ + Q_ASSERT_X(valueOfExpression, "Q_ASSUME()", "Assumption in Q_ASSUME(\"" #Expr "\") was not correct");\ + Q_ASSUME_IMPL(valueOfExpression);\ + }(Expr) + QT_END_NAMESPACE #endif // QASSERT_H diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index 557b1ce0ad4..acbd1c188a0 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -1129,18 +1129,6 @@ #define qMove(x) (x) #endif -#define Q_UNREACHABLE() \ - do {\ - Q_ASSERT_X(false, "Q_UNREACHABLE()", "Q_UNREACHABLE was reached");\ - Q_UNREACHABLE_IMPL();\ - } while (false) - -#define Q_ASSUME(Expr) \ - [] (bool valueOfExpression) {\ - Q_ASSERT_X(valueOfExpression, "Q_ASSUME()", "Assumption in Q_ASSUME(\"" #Expr "\") was not correct");\ - Q_ASSUME_IMPL(valueOfExpression);\ - }(Expr) - #if defined(__cplusplus) #if __has_cpp_attribute(clang::fallthrough) # define Q_FALLTHROUGH() [[clang::fallthrough]] diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 6b8dcdc8465..2852beaaabf 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -2960,67 +2960,6 @@ QByteArray QSysInfo::bootUniqueId() return QByteArray(); }; -/*! - \macro void Q_ASSUME(bool expr) - \relates - \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. - - 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 behaviour may occur. - - 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(). - - In debug builds the condition is enforced by an assert to facilitate debugging. - - \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. - - \sa Q_ASSERT(), Q_UNREACHABLE(), Q_LIKELY() -*/ - -/*! - \macro void Q_UNREACHABLE() - \relates - \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. - - \sa Q_ASSERT(), Q_ASSUME(), qFatal() -*/ - /*! \macro void Q_FALLTHROUGH() \relates @@ -3315,7 +3254,7 @@ void qAbort() \snippet code/src_corelib_global_qglobal.cpp qlikely - \sa Q_UNLIKELY() + \sa Q_UNLIKELY(), Q_ASSUME() */ /*!