Fix support for auto args in constructor callbacks

Broken since 78417b5, this bug creates an infinite recursion at runtime while trying to resolve the QPromise<T> template constructor if the given callback is either an invalid function or a valid callback but using auto args (C++14).

Related warning: C4717: recursive on all control paths, function will cause runtime stack overflow.
This commit is contained in:
Simon Brunel
2020-03-22 16:50:26 +01:00
parent d43657fbd5
commit 6deec9f51f
7 changed files with 136 additions and 4 deletions

View File

@ -1,6 +1,7 @@
add_subdirectory(shared)
add_subdirectory(benchmark)
add_subdirectory(cpp14)
add_subdirectory(deprecations)
add_subdirectory(exceptions)
add_subdirectory(future)

View File

@ -0,0 +1,10 @@
# https://cmake.org/cmake/help/latest/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html
# https://gcc.gnu.org/projects/cxx-status.html#cxx14
if ("cxx_generic_lambdas" IN_LIST CMAKE_CXX_COMPILE_FEATURES)
set(CMAKE_CXX_STANDARD 14)
qtpromise_add_tests(cpp14
SOURCES
tst_argsof_lambda_auto.cpp
tst_resolver_lambda_auto.cpp
)
endif()

View File

@ -0,0 +1,33 @@
/*
* Copyright (c) Simon Brunel, https://github.com/simonbrunel
*
* This source code is licensed under the MIT license found in
* the LICENSE file in the root directory of this source tree.
*/
#include <QtPromise>
#include <QtTest>
using namespace QtPromisePrivate;
class tst_cpp14_argsof_lambda_auto : public QObject
{
Q_OBJECT
private Q_SLOTS:
void lambdaAutoArgs();
};
QTEST_MAIN(tst_cpp14_argsof_lambda_auto)
#include "tst_argsof_lambda_auto.moc"
void tst_cpp14_argsof_lambda_auto::lambdaAutoArgs()
{
auto lOneArg = [](auto) {};
auto lManyArgs = [](const auto&, auto, auto) {};
auto lMutable = [](const auto&, auto) mutable {};
Q_STATIC_ASSERT((ArgsOf<decltype(lOneArg)>::count == 0));
Q_STATIC_ASSERT((ArgsOf<decltype(lManyArgs)>::count == 0));
Q_STATIC_ASSERT((ArgsOf<decltype(lMutable)>::count == 0));
}

View File

@ -0,0 +1,79 @@
/*
* Copyright (c) Simon Brunel, https://github.com/simonbrunel
*
* This source code is licensed under the MIT license found in
* the LICENSE file in the root directory of this source tree.
*/
#include "../shared/utils.h"
#include <QtPromise>
#include <QtTest>
#include <memory>
using namespace QtPromise;
class tst_cpp14_resolver_lambda_auto : public QObject
{
Q_OBJECT
private Q_SLOTS:
void resolverTwoAutoArgs();
void resolverTwoAutoArgs_void();
};
QTEST_MAIN(tst_cpp14_resolver_lambda_auto)
#include "tst_resolver_lambda_auto.moc"
void tst_cpp14_resolver_lambda_auto::resolverTwoAutoArgs()
{
QPromise<int> p0{[](auto resolve, auto reject) {
Q_UNUSED(reject)
resolve(42);
}};
QPromise<int> p1{[](auto resolve, const auto& reject) {
Q_UNUSED(reject)
resolve(42);
}};
QPromise<int> p2{[](const auto& resolve, auto reject) {
Q_UNUSED(reject)
resolve(42);
}};
QPromise<int> p3{[](const auto& resolve, const auto& reject) {
Q_UNUSED(reject)
resolve(42);
}};
for (const auto& p : {p0, p1, p2, p3}) {
QCOMPARE(p.isFulfilled(), true);
QCOMPARE(waitForError(p, -1), -1);
QCOMPARE(waitForValue(p, -1), 42);
}
}
void tst_cpp14_resolver_lambda_auto::resolverTwoAutoArgs_void()
{
QPromise<void> p0{[](auto resolve, auto reject) {
Q_UNUSED(reject)
resolve();
}};
QPromise<void> p1{[](auto resolve, const auto& reject) {
Q_UNUSED(reject)
resolve();
}};
QPromise<void> p2{[](const auto& resolve, auto reject) {
Q_UNUSED(reject)
resolve();
}};
QPromise<void> p3{[](const auto& resolve, const auto& reject) {
Q_UNUSED(reject)
resolve();
}};
for (const auto& p : {p0, p1, p2, p3}) {
QCOMPARE(p.isFulfilled(), true);
QCOMPARE(waitForError(p, -1), -1);
QCOMPARE(waitForValue(p, -1, 42), 42);
}
}