Move Q_ASSUME and Q_UNREACHABLE to qassert.h
As a drive-by, add a link back to Q_ASSUME() in Q_LIKELY() docs. Change-Id: I4a46e281d0fbf55c11001f15667fcc4faa3b0c5b Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Marc Mutz <marc.mutz@qt.io>
This commit is contained in:
parent
1d3fb690cc
commit
29049d23f0
@ -137,4 +137,65 @@ void qBadAlloc()
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
\macro void Q_ASSUME(bool expr)
|
||||
\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.
|
||||
|
||||
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 <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.
|
||||
|
||||
\sa Q_ASSERT(), Q_ASSUME(), qFatal()
|
||||
*/
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -60,6 +60,19 @@ Q_CORE_EXPORT void qBadAlloc();
|
||||
template <typename T>
|
||||
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
|
||||
|
@ -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]]
|
||||
|
@ -2960,67 +2960,6 @@ QByteArray QSysInfo::bootUniqueId()
|
||||
return QByteArray();
|
||||
};
|
||||
|
||||
/*!
|
||||
\macro void Q_ASSUME(bool expr)
|
||||
\relates <QtGlobal>
|
||||
\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 <QtGlobal>
|
||||
\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 <QtGlobal>
|
||||
@ -3315,7 +3254,7 @@ void qAbort()
|
||||
|
||||
\snippet code/src_corelib_global_qglobal.cpp qlikely
|
||||
|
||||
\sa Q_UNLIKELY()
|
||||
\sa Q_UNLIKELY(), Q_ASSUME()
|
||||
*/
|
||||
|
||||
/*!
|
||||
|
Loading…
x
Reference in New Issue
Block a user