diff options
-rw-r--r-- | src/corelib/kernel/qobjectdefs_impl.h | 55 | ||||
-rw-r--r-- | tests/auto/corelib/kernel/qobject/test/test.pro | 3 | ||||
-rw-r--r-- | tests/auto/corelib/kernel/qobject/tst_qobject.cpp | 35 | ||||
-rw-r--r-- | tests/auto/corelib/kernel/qtimer/qtimer.pro | 3 | ||||
-rw-r--r-- | tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp | 8 |
5 files changed, 104 insertions, 0 deletions
diff --git a/src/corelib/kernel/qobjectdefs_impl.h b/src/corelib/kernel/qobjectdefs_impl.h index 79c9c8303e..1768e8ccc6 100644 --- a/src/corelib/kernel/qobjectdefs_impl.h +++ b/src/corelib/kernel/qobjectdefs_impl.h @@ -149,6 +149,20 @@ namespace QtPrivate { (o->*f)((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...), ApplyReturnValue<R>(arg[0]); } }; +#if defined(__cpp_noexcept_function_type) && __cpp_noexcept_function_type >= 201510 + template <int... II, typename... SignalArgs, typename R, typename... SlotArgs, typename SlotRet, class Obj> + struct FunctorCall<IndexesList<II...>, List<SignalArgs...>, R, SlotRet (Obj::*)(SlotArgs...) noexcept> { + static void call(SlotRet (Obj::*f)(SlotArgs...) noexcept, Obj *o, void **arg) { + (o->*f)((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...), ApplyReturnValue<R>(arg[0]); + } + }; + template <int... II, typename... SignalArgs, typename R, typename... SlotArgs, typename SlotRet, class Obj> + struct FunctorCall<IndexesList<II...>, List<SignalArgs...>, R, SlotRet (Obj::*)(SlotArgs...) const noexcept> { + static void call(SlotRet (Obj::*f)(SlotArgs...) const noexcept, Obj *o, void **arg) { + (o->*f)((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...), ApplyReturnValue<R>(arg[0]); + } + }; +#endif template<class Obj, typename Ret, typename... Args> struct FunctionPointer<Ret (Obj::*) (Args...)> { @@ -187,6 +201,47 @@ namespace QtPrivate { } }; +#if defined(__cpp_noexcept_function_type) && __cpp_noexcept_function_type >= 201510 + template<class Obj, typename Ret, typename... Args> struct FunctionPointer<Ret (Obj::*) (Args...) noexcept> + { + typedef Obj Object; + typedef List<Args...> Arguments; + typedef Ret ReturnType; + typedef Ret (Obj::*Function) (Args...) noexcept; + template <class Base> struct ChangeClass { typedef Ret (Base:: *Type)(Args...) noexcept; }; + enum {ArgumentCount = sizeof...(Args), IsPointerToMemberFunction = true}; + template <typename SignalArgs, typename R> + static void call(Function f, Obj *o, void **arg) { + FunctorCall<typename Indexes<ArgumentCount>::Value, SignalArgs, R, Function>::call(f, o, arg); + } + }; + template<class Obj, typename Ret, typename... Args> struct FunctionPointer<Ret (Obj::*) (Args...) const noexcept> + { + typedef Obj Object; + typedef List<Args...> Arguments; + typedef Ret ReturnType; + typedef Ret (Obj::*Function) (Args...) const noexcept; + template <class Base> struct ChangeClass { typedef Ret (Base:: *Type)(Args...) const noexcept; }; + enum {ArgumentCount = sizeof...(Args), IsPointerToMemberFunction = true}; + template <typename SignalArgs, typename R> + static void call(Function f, Obj *o, void **arg) { + FunctorCall<typename Indexes<ArgumentCount>::Value, SignalArgs, R, Function>::call(f, o, arg); + } + }; + + template<typename Ret, typename... Args> struct FunctionPointer<Ret (*) (Args...) noexcept> + { + typedef List<Args...> Arguments; + typedef Ret ReturnType; + typedef Ret (*Function) (Args...) noexcept; + enum {ArgumentCount = sizeof...(Args), IsPointerToMemberFunction = false}; + template <typename SignalArgs, typename R> + static void call(Function f, void *, void **arg) { + FunctorCall<typename Indexes<ArgumentCount>::Value, SignalArgs, R, Function>::call(f, arg); + } + }; +#endif + template<typename Function, int N> struct Functor { template <typename SignalArgs, typename R> diff --git a/tests/auto/corelib/kernel/qobject/test/test.pro b/tests/auto/corelib/kernel/qobject/test/test.pro index f3bc045455..4e77cb48c5 100644 --- a/tests/auto/corelib/kernel/qobject/test/test.pro +++ b/tests/auto/corelib/kernel/qobject/test/test.pro @@ -3,5 +3,8 @@ TARGET = ../tst_qobject QT = core-private network testlib SOURCES = ../tst_qobject.cpp +# Force C++17 if available (needed due to P0012R1) +contains(QT_CONFIG, c++1z): CONFIG += c++1z + !winrt: TEST_HELPER_INSTALLS = ../signalbug/signalbug DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp index 91810cdcd8..7b75438b19 100644 --- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp +++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp @@ -120,6 +120,7 @@ private slots: void connectCxx0x(); void connectToStaticCxx0x(); void connectCxx0xTypeMatching(); + void connectCxx17Noexcept(); void connectConvert(); void connectWithReference(); void connectManyArguments(); @@ -4757,10 +4758,13 @@ class LotsOfSignalsAndSlots: public QObject public slots: void slot_v() {} + void slot_v_noexcept() Q_DECL_NOTHROW {} void slot_vi(int) {} + void slot_vi_noexcept() Q_DECL_NOTHROW {} void slot_vii(int, int) {} void slot_viii(int, int, int) {} int slot_i() { return 0; } + int slot_i_noexcept() Q_DECL_NOTHROW { return 0; } int slot_ii(int) { return 0; } int slot_iii(int, int) { return 0; } int slot_iiii(int, int, int) { return 0; } @@ -4774,13 +4778,18 @@ class LotsOfSignalsAndSlots: public QObject void slot_vPFvvE(fptr) {} void const_slot_v() const {}; + void const_slot_v_noexcept() const Q_DECL_NOTHROW {} void const_slot_vi(int) const {}; + void const_slot_vi_noexcept(int) const Q_DECL_NOTHROW {} static void static_slot_v() {} + static void static_slot_v_noexcept() Q_DECL_NOTHROW {} static void static_slot_vi(int) {} + static void static_slot_vi_noexcept(int) Q_DECL_NOTHROW {} static void static_slot_vii(int, int) {} static void static_slot_viii(int, int, int) {} static int static_slot_i() { return 0; } + static int static_slot_i_noexcept() Q_DECL_NOTHROW { return 0; } static int static_slot_ii(int) { return 0; } static int static_slot_iii(int, int) { return 0; } static int static_slot_iiii(int, int, int) { return 0; } @@ -4943,6 +4952,32 @@ void tst_QObject::connectCxx0xTypeMatching() } +void receiverFunction_noexcept() Q_DECL_NOTHROW {} +struct Functor_noexcept { void operator()() Q_DECL_NOTHROW {} }; +void tst_QObject::connectCxx17Noexcept() +{ + // this is about connecting signals to slots with the Q_DECL_NOTHROW qualifier + // as semantics changed due to http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0012r1.html + typedef LotsOfSignalsAndSlots Foo; + Foo obj; + + QObject::connect(&obj, &Foo::signal_v, &obj, &Foo::slot_v_noexcept); + QObject::connect(&obj, &Foo::signal_v, &obj, &Foo::slot_i_noexcept); + QObject::connect(&obj, &Foo::signal_v, &obj, &Foo::slot_vi_noexcept); + + QObject::connect(&obj, &Foo::signal_vii, &Foo::static_slot_v_noexcept); + QObject::connect(&obj, &Foo::signal_vii, &Foo::static_slot_i_noexcept); + QObject::connect(&obj, &Foo::signal_vii, &Foo::static_slot_vi_noexcept); + + QVERIFY(QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::const_slot_vi_noexcept)); + QVERIFY(QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::const_slot_v_noexcept)); + + QObject::connect(&obj, &Foo::signal_v, receiverFunction_noexcept); + + Functor_noexcept fn; + QObject::connect(&obj, &Foo::signal_v, fn); +} + class StringVariant : public QObject { Q_OBJECT signals: diff --git a/tests/auto/corelib/kernel/qtimer/qtimer.pro b/tests/auto/corelib/kernel/qtimer/qtimer.pro index 8afdbb148e..b27d862bc5 100644 --- a/tests/auto/corelib/kernel/qtimer/qtimer.pro +++ b/tests/auto/corelib/kernel/qtimer/qtimer.pro @@ -2,3 +2,6 @@ CONFIG += testcase TARGET = tst_qtimer QT = core testlib SOURCES = tst_qtimer.cpp + +# Force C++17 if available +contains(QT_CONFIG, c++1z): CONFIG += c++1z diff --git a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp index fe97695d19..29ff552f6a 100644 --- a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp +++ b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp @@ -767,6 +767,11 @@ class StaticEventLoop public: static void quitEventLoop() { + quitEventLoop_noexcept(); + } + + static void quitEventLoop_noexcept() Q_DECL_NOTHROW + { QVERIFY(!_e.isNull()); _e->quit(); if (_t) @@ -787,6 +792,9 @@ void tst_QTimer::singleShotToFunctors() QTimer::singleShot(0, &StaticEventLoop::quitEventLoop); QCOMPARE(_e->exec(), 0); + QTimer::singleShot(0, &StaticEventLoop::quitEventLoop_noexcept); + QCOMPARE(_e->exec(), 0); + QThread t1; QObject c1; c1.moveToThread(&t1); |