Short live Q_NODISCARD_CTOR
[ChangeLog][QtCore] Introduced Q_NODISCARD_CTOR which resolves to [[nodiscard]] attribute for constructors on compilers that support it, and does nothing on other compilers. Using [[nodiscard]] attribute on a constructor is a C++20 feature, however in practice it is supported on most of the compilers that we use in Qt 6. Clang generates a [-Wunused-value] warning, GCC and MinGW generate a [-Wunused-result] warnings, and MSVC generates a C4834 warning. However, there are some exceptions. The Integrity compiler provides the following warning: "tst_qglobal.cpp", line 699: warning #3435-D: the "nodiscard" attribute doesn't apply to constructors, destructors, or routines with void return type [[nodiscard]] explicit Test(int val) : m_val(val) {} The QNX compiler (QCC 8.3.0) and GCC 9.3.1 on OpenSUSE generate the [-Wattributes] warning: tst_qglobal.cpp: In member function 'void tst_QGlobal::nodiscardConstructor()': tst_qglobal.cpp:699:44: warning: 'nodiscard' attribute applied to 'tst_QGlobal::nodiscardConstructor()::Test::Test(int)' with void return type [-Wattributes] [[nodiscard]] explicit Test(int val) : m_val(val) {} These warnings will lead to build failures when compiled with -warnings-are-errors flag, so for these compilers the macro does not do anything. An attempt to use __attribute__((__warn_unused_result__)) was also unsuccessful on these compilers, so this patch goes for an easy solution, and simply checks __has_cpp_attribute(nodiscard) >= 201907L to decide if the attribute is supported or not. This commit also introduces a syntax-only test, and also applies the new macro to QMutexLocker, because not all platforms in the CI build and run unit tests. Fixes: QTBUG-104161 Change-Id: Ib4230661a5ad5e8af0d67b21b034486ebcd67562 Reviewed-by: Marc Mutz <marc.mutz@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
parent
d3b3fc538b
commit
959800f6de
@ -970,6 +970,15 @@
|
|||||||
#define Q_DECL_ENUMERATOR_DEPRECATED Q_DECL_DEPRECATED
|
#define Q_DECL_ENUMERATOR_DEPRECATED Q_DECL_DEPRECATED
|
||||||
#define Q_DECL_ENUMERATOR_DEPRECATED_X(x) Q_DECL_DEPRECATED_X(x)
|
#define Q_DECL_ENUMERATOR_DEPRECATED_X(x) Q_DECL_DEPRECATED_X(x)
|
||||||
|
|
||||||
|
// [[nodiscard]] constructor
|
||||||
|
#ifndef Q_NODISCARD_CTOR
|
||||||
|
# if __has_cpp_attribute(nodiscard) >= 201907L
|
||||||
|
# define Q_NODISCARD_CTOR [[nodiscard]]
|
||||||
|
# else
|
||||||
|
# define Q_NODISCARD_CTOR
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fallback macros to certain compiler features
|
* Fallback macros to certain compiler features
|
||||||
*/
|
*/
|
||||||
|
@ -231,6 +231,7 @@ template <typename Mutex>
|
|||||||
class [[nodiscard]] QMutexLocker
|
class [[nodiscard]] QMutexLocker
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
Q_NODISCARD_CTOR
|
||||||
inline explicit QMutexLocker(Mutex *mutex) QT_MUTEX_LOCK_NOEXCEPT
|
inline explicit QMutexLocker(Mutex *mutex) QT_MUTEX_LOCK_NOEXCEPT
|
||||||
{
|
{
|
||||||
m_mutex = mutex;
|
m_mutex = mutex;
|
||||||
@ -240,6 +241,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Q_NODISCARD_CTOR
|
||||||
inline QMutexLocker(QMutexLocker &&other) noexcept
|
inline QMutexLocker(QMutexLocker &&other) noexcept
|
||||||
: m_mutex(std::exchange(other.m_mutex, nullptr)),
|
: m_mutex(std::exchange(other.m_mutex, nullptr)),
|
||||||
m_isLocked(std::exchange(other.m_isLocked, false))
|
m_isLocked(std::exchange(other.m_isLocked, false))
|
||||||
@ -326,6 +328,7 @@ template <typename Mutex>
|
|||||||
class [[nodiscard]] QMutexLocker
|
class [[nodiscard]] QMutexLocker
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
Q_NODISCARD_CTOR
|
||||||
inline explicit QMutexLocker(Mutex *) noexcept {}
|
inline explicit QMutexLocker(Mutex *) noexcept {}
|
||||||
inline ~QMutexLocker() noexcept {}
|
inline ~QMutexLocker() noexcept {}
|
||||||
|
|
||||||
|
@ -37,6 +37,7 @@ private slots:
|
|||||||
void qRoundDoubles();
|
void qRoundDoubles();
|
||||||
void PRImacros();
|
void PRImacros();
|
||||||
void testqToUnderlying();
|
void testqToUnderlying();
|
||||||
|
void nodiscardConstructor();
|
||||||
};
|
};
|
||||||
|
|
||||||
extern "C" { // functions in qglobal.c
|
extern "C" { // functions in qglobal.c
|
||||||
@ -691,5 +692,25 @@ void tst_QGlobal::testqToUnderlying()
|
|||||||
QCOMPARE(qToUnderlying(EE2), 456UL);
|
QCOMPARE(qToUnderlying(EE2), 456UL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QGlobal::nodiscardConstructor()
|
||||||
|
{
|
||||||
|
// Syntax-only test, just to make sure that Q_NODISCARD_CTOR compiles
|
||||||
|
// on all platforms.
|
||||||
|
// Other code is just to silence all various compiler warnings about
|
||||||
|
// unused private members or methods.
|
||||||
|
class Test {
|
||||||
|
public:
|
||||||
|
Q_NODISCARD_CTOR explicit Test(int val) : m_val(val) {}
|
||||||
|
|
||||||
|
int get() const { return m_val; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_val;
|
||||||
|
};
|
||||||
|
|
||||||
|
Test t{42};
|
||||||
|
QCOMPARE(t.get(), 42);
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_APPLESS_MAIN(tst_QGlobal)
|
QTEST_APPLESS_MAIN(tst_QGlobal)
|
||||||
#include "tst_qglobal.moc"
|
#include "tst_qglobal.moc"
|
||||||
|
Loading…
Reference in New Issue
Block a user