diff options
-rw-r--r-- | doc/src/snippets/code/src_corelib_global_qglobal.cpp | 23 | ||||
-rw-r--r-- | src/corelib/global/qcompilerdetection.h | 8 | ||||
-rw-r--r-- | src/corelib/global/qglobal.cpp | 57 | ||||
-rw-r--r-- | src/corelib/global/qglobal.h | 6 |
4 files changed, 94 insertions, 0 deletions
diff --git a/doc/src/snippets/code/src_corelib_global_qglobal.cpp b/doc/src/snippets/code/src_corelib_global_qglobal.cpp index 21bea7aef8..16f6783a52 100644 --- a/doc/src/snippets/code/src_corelib_global_qglobal.cpp +++ b/doc/src/snippets/code/src_corelib_global_qglobal.cpp @@ -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] diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index f3f0302072..c9f59454b2 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -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) diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 09d178639d..f89b0b3421 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -1799,6 +1799,63 @@ const QSysInfo::WinVersion QSysInfo::WindowsVersion = QSysInfo::windowsVersion() */ /*! + \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> diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 734177638c..7d91fa3ca9 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -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) |