diff options
author | Marc Mutz <marc.mutz@kdab.com> | 2012-08-07 01:54:13 +0200 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-08-07 21:11:55 +0200 |
commit | f829ab5573f7146785c79d83182757043b0e6ce9 (patch) | |
tree | bf164c6f38044de5df0e5dde19ab8cae84bb9e7b /src | |
parent | 46212d657e2e989dddd361a732e65b05748e8e91 (diff) |
Q_DECL_NOTHROW: stronger and more widely available version of Q_DECL_NOEXCEPT
Commit 1adca807 defined Q_DECL_NOEXCEPT to be the same as throw() for the
Microsoft compiler. However, the two are not equivalent:
- C++11 noexcept is defined to call std::terminate() if a noexcept
function nevertheless encounters an exception.
- MSVC throw() has essentially undefined behaviour in this situation:
http://msdn.microsoft.com/en-us/library/wfa0edys%28v=vs.100%29
"Due to code optimizations that might be performed by the C++
compiler [...] if a function does throw an exception, the program
may not execute correctly."
So define two macros:
1. Q_DECL_NOEXCEPT/Q_DECL_NOEXCEPT_EXPR always have C++11 behaviour.
This is expected to be the more efficient implementation if the
function can actually throw.
2. Q_DECL_NOTHROW means that the function gives the nothrow
guarantee. It is stronger than noexcept, but not all functions
that can be marked Q_DECL_NOEXCEPT can be marked Q_DECL_NOTHROW.
In general Q_DECL_NOTHROW functions need to use a try/catch block
in order to prevent exceptions from leaving the functions, unless
you can proove that none of the operations can throw.
For the caller, both macros are equivalent: it can be relied on that
no exception leaves the function.
Change-Id: I32f822a82e06a31cb71d38db438387aee5ec3334
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Marius Storm-Olsen <marius.storm-olsen@nokia.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/global/qcompilerdetection.h | 14 | ||||
-rw-r--r-- | src/corelib/global/qglobal.cpp | 63 |
2 files changed, 73 insertions, 4 deletions
diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index 64aae8acb2..be167f2a2a 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -110,9 +110,9 @@ # define Q_COMPILER_VARIADIC_MACROS # endif -// make sure that these aren't defined when Q_COMPILER_NOEXCEPT is defined -# define Q_DECL_NOEXCEPT throw() -# define Q_DECL_NOEXCEPT_EXPR(x) +/* only defined for MSVC since that's the only compiler that actually optimizes for this */ +/* might get overridden further down when Q_COMPILER_NOEXCEPT is detected */ +# define Q_DECL_NOTHROW throw() #elif defined(__BORLANDC__) || defined(__TURBOC__) # define Q_CC_BOR @@ -717,10 +717,16 @@ #ifdef Q_COMPILER_NOEXCEPT # define Q_DECL_NOEXCEPT noexcept # define Q_DECL_NOEXCEPT_EXPR(x) noexcept(x) -#elif !defined(Q_DECL_NOEXCEPT) +# ifdef Q_DECL_NOTHROW +# undef Q_DECL_NOTHROW /* override with C++11 noexcept if available */ +# endif +#else # define Q_DECL_NOEXCEPT # define Q_DECL_NOEXCEPT_EXPR(x) #endif +#ifndef Q_DECL_NOTHROW +# define Q_DECL_NOTHROW Q_DECL_NOEXCEPT +#endif #if defined(Q_COMPILER_ALIGNOF) && !defined(Q_ALIGNOF) # define Q_ALIGNOF(x) alignof(x) diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 087e33ba36..61ae53b103 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -3014,4 +3014,67 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters) otherwise. */ +/*! + \macro Q_DECL_NOTHROW + \relates <QtGlobal> + \since 5.0 + + This macro marks a function as never throwing, under no + circumstances. If the function does nevertheless throw, the + behaviour is undefined. + + The macro expands to either "throw()", if that has some benefit on + the compiler, or to C++11 noexcept, if available, or to nothing + otherwise. + + If you need C++11 noexcept semantics, don't use this macro, use + Q_DECL_NOEXCEPT/Q_DECL_NOEXCEPT_EXPR instead. + + \sa Q_DECL_NOEXCEPT, Q_DECL_NOEXCEPT_EXPR +*/ + +/*! + \macro Q_DECL_NOEXCEPT + \relates <QtGlobal> + \since 5.0 + + This macro marks a function as never throwing. If the function + does nevertheless throw, the behaviour is defined: + std::terminate() is called. + + The macro expands to C++11 noexcept, if available, or to nothing + otherwise. + + If you need the operator version of C++11 noexcept, use + Q_DECL_NOEXCEPT_EXPR(x). + + If you don't need C++11 noexcept semantics, e.g. because your + function can't possibly throw, don't use this macro, use + Q_DECL_NOTHROW instead. + + \sa Q_DECL_NOTHROW, Q_DECL_NOEXCEPT_EXPR +*/ + +/*! + \macro Q_DECL_NOEXCEPT_EXPR(x) + \relates <QtGlobal> + \since 5.0 + + This macro marks a function as non-throwing if \a x is true. If + the function does nevertheless throw, the behaviour is defined: + std::terminate() is called. + + The macro expands to C++11 noexcept(x), if available, or to + nothing otherwise. + + If you need the always-true version of C++11 noexcept, use + Q_DECL_NOEXCEPT. + + If you don't need C++11 noexcept semantics, e.g. because your + function can't possibly throw, don't use this macro, use + Q_DECL_NOTHROW instead. + + \sa Q_DECL_NOTHROW, Q_DECL_NOEXCEPT_EXPR +*/ + QT_END_NAMESPACE |