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
|
#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
|
QT_END_NAMESPACE
|
||||||
|
@ -60,6 +60,19 @@ Q_CORE_EXPORT void qBadAlloc();
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
inline T *q_check_ptr(T *p) { Q_CHECK_PTR(p); return p; }
|
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
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
#endif // QASSERT_H
|
#endif // QASSERT_H
|
||||||
|
@ -1129,18 +1129,6 @@
|
|||||||
#define qMove(x) (x)
|
#define qMove(x) (x)
|
||||||
#endif
|
#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 defined(__cplusplus)
|
||||||
#if __has_cpp_attribute(clang::fallthrough)
|
#if __has_cpp_attribute(clang::fallthrough)
|
||||||
# define Q_FALLTHROUGH() [[clang::fallthrough]]
|
# define Q_FALLTHROUGH() [[clang::fallthrough]]
|
||||||
|
@ -2960,67 +2960,6 @@ QByteArray QSysInfo::bootUniqueId()
|
|||||||
return QByteArray();
|
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()
|
\macro void Q_FALLTHROUGH()
|
||||||
\relates <QtGlobal>
|
\relates <QtGlobal>
|
||||||
@ -3315,7 +3254,7 @@ void qAbort()
|
|||||||
|
|
||||||
\snippet code/src_corelib_global_qglobal.cpp qlikely
|
\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