Add macros for assuming and unreachable code
Use these macros to tell the compiler about conditions that may happen, so it will generate better code. But do not assume that they will do anything special. Change-Id: I89ec4f65f48a9340ccf5ffc4ae4b8c3d8897c8b1 Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@nokia.com> Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
This commit is contained in:
parent
4131c323a3
commit
ad81f75429
@ -560,3 +560,26 @@ bool readConfiguration(const QFile &file)
|
||||
return true;
|
||||
}
|
||||
//! [qunlikely]
|
||||
|
||||
//! [qunreachable-enum]
|
||||
enum Shapes {
|
||||
Rectangle,
|
||||
Triangle,
|
||||
Circle,
|
||||
NumShapes
|
||||
};
|
||||
//! [qunreachable-enum]
|
||||
|
||||
//! [qunreachable-switch]
|
||||
switch (shape) {
|
||||
case Rectangle:
|
||||
return rectangle();
|
||||
case Triangle:
|
||||
return triangle();
|
||||
case Circle:
|
||||
return circle();
|
||||
case NumShapes:
|
||||
Q_UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
//! [qunreachable-switch]
|
||||
|
@ -88,6 +88,8 @@
|
||||
# define Q_NO_TEMPLATE_FRIENDS
|
||||
# define Q_ALIGNOF(type) __alignof(type)
|
||||
# define Q_DECL_ALIGN(n) __declspec(align(n))
|
||||
# define Q_ASSUME(expr) __assume(expr)
|
||||
# define Q_UNREACHABLE() __assume(0)
|
||||
/* Intel C++ disguising as Visual C++: the `using' keyword avoids warnings */
|
||||
# if defined(__INTEL_COMPILER)
|
||||
# define Q_CC_INTEL
|
||||
@ -141,11 +143,17 @@
|
||||
# if defined(__INTEL_COMPILER)
|
||||
/* Intel C++ also masquerades as GCC */
|
||||
# define Q_CC_INTEL
|
||||
# define Q_ASSUME(expr) __assume(expr)
|
||||
# define Q_UNREACHABLE() __assume(0)
|
||||
# elif defined(__clang__)
|
||||
/* Clang also masquerades as GCC */
|
||||
# define Q_CC_CLANG
|
||||
# define Q_ASSUME(expr) if (expr){} else __builtin_unreachable()
|
||||
# define Q_UNREACHABLE() __builtin_unreachable()
|
||||
# else
|
||||
/* Plain GCC */
|
||||
# define Q_ASSUME(expr) if (expr){} else __builtin_unreachable()
|
||||
# define Q_UNREACHABLE() __builtin_unreachable()
|
||||
# endif
|
||||
|
||||
# define Q_ALIGNOF(type) __alignof__(type)
|
||||
|
@ -1798,6 +1798,63 @@ const QSysInfo::WinVersion QSysInfo::WindowsVersion = QSysInfo::windowsVersion()
|
||||
\sa Q_ASSERT(), qFatal(), {Debugging Techniques}
|
||||
*/
|
||||
|
||||
/*!
|
||||
\macro void Q_ASSUME(bool expr)
|
||||
\relates <QtGlobal>
|
||||
\since 5.0
|
||||
|
||||
Causes the compiler to assume that \a expr is 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 \ref Q_ASSERT. While
|
||||
Q_ASSERT will abort the program's execution if the condition is 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 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().
|
||||
|
||||
\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 optimise 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 doc/src/snippets/code/src_corelib_global_qglobal.cpp qunreachable-enum
|
||||
|
||||
One can write a switch table like so:
|
||||
|
||||
\snippet doc/src/snippets/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.
|
||||
|
||||
\sa Q_ASSERT(), Q_ASSUME(), qFatal()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\macro void Q_CHECK_PTR(void *pointer)
|
||||
\relates <QtGlobal>
|
||||
|
@ -163,6 +163,12 @@ namespace QT_NAMESPACE {}
|
||||
#ifndef Q_UNLIKELY
|
||||
# define Q_UNLIKELY(x) (x)
|
||||
#endif
|
||||
#ifndef Q_ASSUME
|
||||
# define Q_ASSUME(expr)
|
||||
#endif
|
||||
#ifndef Q_UNREACHABLE
|
||||
# define Q_UNREACHABLE()
|
||||
#endif
|
||||
|
||||
#ifndef Q_ALLOC_SIZE
|
||||
# define Q_ALLOC_SIZE(x)
|
||||
|
Loading…
Reference in New Issue
Block a user