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>
This commit is contained in:
Marc Mutz 2012-08-07 01:54:13 +02:00 committed by Qt by Nokia
parent 46212d657e
commit f829ab5573
2 changed files with 73 additions and 4 deletions

View File

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

View File

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