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:
Thiago Macieira 2011-12-31 00:15:06 -02:00 committed by Qt by Nokia
parent 4131c323a3
commit ad81f75429
4 changed files with 94 additions and 0 deletions

View File

@ -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]

View File

@ -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)

View File

@ -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>

View File

@ -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)