diff --git a/src/concurrent/CMakeLists.txt b/src/concurrent/CMakeLists.txt index 7dfc9e911e6..504f8545345 100644 --- a/src/concurrent/CMakeLists.txt +++ b/src/concurrent/CMakeLists.txt @@ -28,6 +28,7 @@ qt_internal_add_module(Concurrent QT_NO_CONTEXTLESS_CONNECT QT_NO_FOREACH QT_NO_USING_NAMESPACE + QT_USE_NODISCARD_FILE_OPEN LIBRARIES Qt::CorePrivate PUBLIC_LIBRARIES diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt index c9e788054f9..8c2f62ef03b 100644 --- a/src/corelib/CMakeLists.txt +++ b/src/corelib/CMakeLists.txt @@ -323,6 +323,7 @@ qt_internal_add_module(Core QT_NO_QPAIR QT_NO_USING_NAMESPACE QT_TYPESAFE_FLAGS + QT_USE_NODISCARD_FILE_OPEN INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/global" "${CMAKE_CURRENT_BINARY_DIR}/kernel" # for moc_qobject.cpp to be found by qobject.cpp diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index eb06a950146..222c008f8a2 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -346,6 +346,7 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters) \row \li 6.6.0 \li The qExchange() function (see \l{QT_NO_QEXCHANGE}) \row \li 6.7.0 \li Overloads of QObject::connect that do not take a context object (see \l{QT_NO_CONTEXTLESS_CONNECT}) \row \li 6.8.0 \li The qAsConst() function (see \l{QT_NO_QASCONST}) + \row \li 6.8.0 \li File-related I/O classes have their \c{open()} functions marked \c{[[nodiscard]]} (see \l{QT_USE_NODISCARD_FILE_OPEN}) \endtable Moreover, individual APIs may also get disabled as part of the diff --git a/src/corelib/global/qtconfigmacros.h b/src/corelib/global/qtconfigmacros.h index ee7ebca52bd..018161eac4c 100644 --- a/src/corelib/global/qtconfigmacros.h +++ b/src/corelib/global/qtconfigmacros.h @@ -199,6 +199,9 @@ namespace QT_NAMESPACE {} #if QT_ENABLE_STRICT_MODE_UP_TO >= QT_VERSION_CHECK(6, 8, 0) # define QT_NO_QASCONST +# if !defined(QT_USE_NODISCARD_FILE_OPEN) && !defined(QT_NO_USE_NODISCARD_FILE_OPEN) +# define QT_USE_NODISCARD_FILE_OPEN +# endif #endif // 6.8.0 #endif // QT_ENABLE_STRICT_MODE_UP_TO diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp index 6da428f58c4..52188dde516 100644 --- a/src/corelib/io/qfile.cpp +++ b/src/corelib/io/qfile.cpp @@ -897,6 +897,8 @@ QFile::copy(const QString &fileName, const QString &newName) of the file name, otherwise, it won't be possible to create this non-existing file. + \sa QT_USE_NODISCARD_FILE_OPEN + \sa QIODevice::OpenMode, setFileName() */ bool QFile::open(OpenMode mode) @@ -941,7 +943,7 @@ bool QFile::open(OpenMode mode) such permissions will generate warnings when the Security tab of the Properties dialog is opened. Granting the group all permissions granted to others avoids such warnings. - \sa QIODevice::OpenMode, setFileName() + \sa QIODevice::OpenMode, setFileName(), QT_USE_NODISCARD_FILE_OPEN \since 6.3 */ bool QFile::open(OpenMode mode, QFile::Permissions permissions) @@ -998,7 +1000,7 @@ bool QFile::open(OpenMode mode, QFile::Permissions permissions) you cannot use this QFile with a QFileInfo. \endlist - \sa close() + \sa close(), QT_USE_NODISCARD_FILE_OPEN \b{Note for the Windows Platform} @@ -1064,7 +1066,7 @@ bool QFile::open(FILE *fh, OpenMode mode, FileHandleFlags handleFlags) \warning Since this function opens the file without specifying the file name, you cannot use this QFile with a QFileInfo. - \sa close() + \sa close(), QT_USE_NODISCARD_FILE_OPEN */ bool QFile::open(int fd, OpenMode mode, FileHandleFlags handleFlags) { diff --git a/src/corelib/io/qfile.h b/src/corelib/io/qfile.h index 1d18dd55c03..058b2fa2363 100644 --- a/src/corelib/io/qfile.h +++ b/src/corelib/io/qfile.h @@ -282,10 +282,10 @@ public: } #endif // QT_CONFIG(cxx17_filesystem) - bool open(OpenMode flags) override; - bool open(OpenMode flags, Permissions permissions); - bool open(FILE *f, OpenMode ioFlags, FileHandleFlags handleFlags=DontCloseHandle); - bool open(int fd, OpenMode ioFlags, FileHandleFlags handleFlags=DontCloseHandle); + QFILE_MAYBE_NODISCARD bool open(OpenMode flags) override; + QFILE_MAYBE_NODISCARD bool open(OpenMode flags, Permissions permissions); + QFILE_MAYBE_NODISCARD bool open(FILE *f, OpenMode ioFlags, FileHandleFlags handleFlags=DontCloseHandle); + QFILE_MAYBE_NODISCARD bool open(int fd, OpenMode ioFlags, FileHandleFlags handleFlags=DontCloseHandle); qint64 size() const override; diff --git a/src/corelib/io/qfiledevice.cpp b/src/corelib/io/qfiledevice.cpp index d3b493a1ccb..431dc65f5b8 100644 --- a/src/corelib/io/qfiledevice.cpp +++ b/src/corelib/io/qfiledevice.cpp @@ -168,6 +168,35 @@ void QFileDevicePrivate::setError(QFileDevice::FileError err, int errNum) handle is left open when the QFile object is destroyed. */ +/*! + \macro QT_USE_NODISCARD_FILE_OPEN + \macro QT_NO_USE_NODISCARD_FILE_OPEN + \relates QFileDevice + \since 6.8 + + File-related I/O classes (such as QFile, QSaveFile, QTemporaryFile) + have an \c{open()} method to open the file they act upon. It is + important to check the return value of the call to \c{open()} + before proceeding with reading or writing data into the file. + + For this reason, starting with Qt 6.8, some overloads of \c{open()} + have been marked with the \c{[[nodiscard]]} attribute. Since this + change may raise warnings in existing codebases, user code can + opt-in or opt-out from having the attribute applied by defining + certain macros: + + \list + \li If the \c{QT_USE_NODISCARD_FILE_OPEN} macro is defined, + overloads of \c{open()} are marked as \c{[[nodiscard]]}. + \li If the \c{QT_NO_USE_NODISCARD_FILE_OPEN} is defined, the + overloads of \c{open()} are \e{not} marked as \c{[[nodiscard]]}. + \li If neither macro is defined, then the default up to and + including Qt 6.9 is not to have the attribute. Starting from Qt 6.10, + the attribute is automatically applied. + \li If both macros are defined, the program is ill-formed. + \endlist +*/ + #ifdef QT_NO_QOBJECT QFileDevice::QFileDevice() : QIODevice(*new QFileDevicePrivate) diff --git a/src/corelib/io/qfiledevice.h b/src/corelib/io/qfiledevice.h index 79788e2aafb..52740257154 100644 --- a/src/corelib/io/qfiledevice.h +++ b/src/corelib/io/qfiledevice.h @@ -12,6 +12,22 @@ QT_BEGIN_NAMESPACE class QDateTime; class QFileDevicePrivate; +#if !defined(QT_USE_NODISCARD_FILE_OPEN) && !defined(QT_NO_USE_NODISCARD_FILE_OPEN) +# if QT_VERSION < QT_VERSION_CHECK(6, 10, 0) +# define QT_NO_USE_NODISCARD_FILE_OPEN +# else +# define QT_USE_NODISCARD_FILE_OPEN +# endif +#endif + +#if defined(QT_USE_NODISCARD_FILE_OPEN) && defined(QT_NO_USE_NODISCARD_FILE_OPEN) +#error "Inconsistent macro definition for nodiscard QFile::open" +#elif defined(QT_USE_NODISCARD_FILE_OPEN) +#define QFILE_MAYBE_NODISCARD [[nodiscard]] +#else /* QT_NO_USE_NODISCARD_FILE_OPEN */ +#define QFILE_MAYBE_NODISCARD +#endif + class Q_CORE_EXPORT QFileDevice : public QIODevice { #ifndef QT_NO_QOBJECT diff --git a/src/corelib/io/qsavefile.cpp b/src/corelib/io/qsavefile.cpp index 9041775d99c..6d8918c29c6 100644 --- a/src/corelib/io/qsavefile.cpp +++ b/src/corelib/io/qsavefile.cpp @@ -152,7 +152,7 @@ void QSaveFile::setFileName(const QString &name) QIODevice::ReadWrite, QIODevice::Append, QIODevice::NewOnly and QIODevice::ExistingOnly are not supported at the moment. - \sa QIODevice::OpenMode, setFileName() + \sa QIODevice::OpenMode, setFileName(), QT_USE_NODISCARD_FILE_OPEN */ bool QSaveFile::open(OpenMode mode) { diff --git a/src/corelib/io/qsavefile.h b/src/corelib/io/qsavefile.h index db8a25507c7..4dd712d4b60 100644 --- a/src/corelib/io/qsavefile.h +++ b/src/corelib/io/qsavefile.h @@ -39,7 +39,7 @@ public: QString fileName() const override; void setFileName(const QString &name); - bool open(OpenMode flags) override; + QFILE_MAYBE_NODISCARD bool open(OpenMode flags) override; bool commit(); void cancelWriting(); diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp index 59f52bd082b..116c351962e 100644 --- a/src/corelib/io/qtemporaryfile.cpp +++ b/src/corelib/io/qtemporaryfile.cpp @@ -725,7 +725,7 @@ QTemporaryFile::~QTemporaryFile() return true upon success and will set the fileName() to the unique filename used. - \sa fileName() + \sa fileName(), QT_USE_NODISCARD_FILE_OPEN */ /*! diff --git a/src/corelib/io/qtemporaryfile.h b/src/corelib/io/qtemporaryfile.h index 9d07e1633bb..9a4476f9d21 100644 --- a/src/corelib/io/qtemporaryfile.h +++ b/src/corelib/io/qtemporaryfile.h @@ -48,7 +48,7 @@ public: void setAutoRemove(bool b); // ### Hides open(flags) - bool open() { return open(QIODevice::ReadWrite); } + QFILE_MAYBE_NODISCARD bool open() { return open(QIODevice::ReadWrite); } QString fileName() const override; QString fileTemplate() const; diff --git a/src/dbus/CMakeLists.txt b/src/dbus/CMakeLists.txt index cefd12b986d..9c3f6d23d2c 100644 --- a/src/dbus/CMakeLists.txt +++ b/src/dbus/CMakeLists.txt @@ -47,6 +47,7 @@ qt_internal_add_module(DBus QT_NO_CONTEXTLESS_CONNECT QT_NO_FOREACH QT_NO_QPAIR + QT_USE_NODISCARD_FILE_OPEN LIBRARIES Qt::CorePrivate PUBLIC_LIBRARIES diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 5f5ed6d66b5..87621e4c680 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -266,6 +266,7 @@ qt_internal_add_module(Gui QT_NO_CONTEXTLESS_CONNECT QT_NO_FOREACH QT_NO_USING_NAMESPACE + QT_USE_NODISCARD_FILE_OPEN QT_QPA_DEFAULT_PLATFORM_NAME="${QT_QPA_DEFAULT_PLATFORM}" INCLUDE_DIRECTORIES ../3rdparty/VulkanMemoryAllocator diff --git a/src/network/CMakeLists.txt b/src/network/CMakeLists.txt index 38e653ce93b..f68198df588 100644 --- a/src/network/CMakeLists.txt +++ b/src/network/CMakeLists.txt @@ -62,6 +62,7 @@ qt_internal_add_module(Network QT_NO_CAST_TO_ASCII QT_NO_CAST_FROM_BYTEARRAY QT_NO_URL_CAST_FROM_STRING + QT_USE_NODISCARD_FILE_OPEN INCLUDE_DIRECTORIES kernel LIBRARIES diff --git a/src/opengl/CMakeLists.txt b/src/opengl/CMakeLists.txt index cbb2a2b338e..825e4cb71b5 100644 --- a/src/opengl/CMakeLists.txt +++ b/src/opengl/CMakeLists.txt @@ -39,6 +39,7 @@ qt_internal_add_module(OpenGL QT_NO_CONTEXTLESS_CONNECT QT_NO_FOREACH QT_NO_USING_NAMESPACE + QT_USE_NODISCARD_FILE_OPEN LIBRARIES Qt::CorePrivate Qt::GuiPrivate diff --git a/src/openglwidgets/CMakeLists.txt b/src/openglwidgets/CMakeLists.txt index fff233dd206..af3efdf30f7 100644 --- a/src/openglwidgets/CMakeLists.txt +++ b/src/openglwidgets/CMakeLists.txt @@ -13,6 +13,7 @@ qt_internal_add_module(OpenGLWidgets QT_NO_CONTEXTLESS_CONNECT QT_NO_FOREACH QT_NO_USING_NAMESPACE + QT_USE_NODISCARD_FILE_OPEN LIBRARIES Qt::OpenGLPrivate Qt::WidgetsPrivate diff --git a/src/printsupport/CMakeLists.txt b/src/printsupport/CMakeLists.txt index 0b13146cf9f..25aad04cafd 100644 --- a/src/printsupport/CMakeLists.txt +++ b/src/printsupport/CMakeLists.txt @@ -23,6 +23,7 @@ qt_internal_add_module(PrintSupport QT_NO_CONTEXTLESS_CONNECT QT_NO_FOREACH QT_NO_USING_NAMESPACE + QT_USE_NODISCARD_FILE_OPEN INCLUDE_DIRECTORIES dialogs widgets diff --git a/src/sql/CMakeLists.txt b/src/sql/CMakeLists.txt index dbd7cf99bfe..0a51f62c4bc 100644 --- a/src/sql/CMakeLists.txt +++ b/src/sql/CMakeLists.txt @@ -26,6 +26,7 @@ qt_internal_add_module(Sql QT_NO_CONTEXTLESS_CONNECT QT_NO_FOREACH QT_NO_USING_NAMESPACE + QT_USE_NODISCARD_FILE_OPEN LIBRARIES Qt::CorePrivate PUBLIC_LIBRARIES diff --git a/src/testlib/CMakeLists.txt b/src/testlib/CMakeLists.txt index bafef623d0b..2c33883c96f 100644 --- a/src/testlib/CMakeLists.txt +++ b/src/testlib/CMakeLists.txt @@ -65,6 +65,7 @@ qt_internal_add_module(Test QT_NO_CONTEXTLESS_CONNECT QT_NO_DATASTREAM QT_NO_FOREACH + QT_USE_NODISCARD_FILE_OPEN # Ensure uniform location info between release and debug builds QT_NO_MESSAGELOGCONTEXT LIBRARIES diff --git a/src/tools/moc/CMakeLists.txt b/src/tools/moc/CMakeLists.txt index f56156d39d3..b98b7ab4e9b 100644 --- a/src/tools/moc/CMakeLists.txt +++ b/src/tools/moc/CMakeLists.txt @@ -30,6 +30,7 @@ qt_internal_add_tool(${target_name} QT_NO_CAST_FROM_BYTEARRAY QT_NO_FOREACH QT_NO_QPAIR + QT_USE_NODISCARD_FILE_OPEN INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR} ../../3rdparty/tinycbor/src diff --git a/src/tools/qlalr/CMakeLists.txt b/src/tools/qlalr/CMakeLists.txt index 89aecf2bdf1..da8b3518893 100644 --- a/src/tools/qlalr/CMakeLists.txt +++ b/src/tools/qlalr/CMakeLists.txt @@ -22,6 +22,7 @@ qt_internal_add_tool(${target_name} DEFINES QT_NO_FOREACH QT_NO_QPAIR + QT_USE_NODISCARD_FILE_OPEN LIBRARIES Qt::Core Qt::CorePrivate diff --git a/src/tools/rcc/CMakeLists.txt b/src/tools/rcc/CMakeLists.txt index 55d4de2e285..35a72c43fe5 100644 --- a/src/tools/rcc/CMakeLists.txt +++ b/src/tools/rcc/CMakeLists.txt @@ -18,6 +18,7 @@ qt_internal_add_tool(${target_name} QT_NO_CAST_FROM_ASCII QT_NO_FOREACH QT_RCC + QT_USE_NODISCARD_FILE_OPEN INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR} ) diff --git a/src/tools/uic/CMakeLists.txt b/src/tools/uic/CMakeLists.txt index 48c1a535464..9f47ec8b4b0 100644 --- a/src/tools/uic/CMakeLists.txt +++ b/src/tools/uic/CMakeLists.txt @@ -32,6 +32,7 @@ qt_internal_add_tool(${target_name} DEFINES QT_NO_CAST_FROM_ASCII QT_NO_FOREACH + QT_USE_NODISCARD_FILE_OPEN QT_UIC INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR} diff --git a/src/widgets/CMakeLists.txt b/src/widgets/CMakeLists.txt index 2ba8e4719a7..fdef309a4ae 100644 --- a/src/widgets/CMakeLists.txt +++ b/src/widgets/CMakeLists.txt @@ -55,6 +55,7 @@ qt_internal_add_module(Widgets QT_NO_CONTEXTLESS_CONNECT QT_NO_USING_NAMESPACE QT_NO_FOREACH + QT_USE_NODISCARD_FILE_OPEN INCLUDE_DIRECTORIES dialogs LIBRARIES diff --git a/src/xml/CMakeLists.txt b/src/xml/CMakeLists.txt index 58c43f23849..38b52e3a086 100644 --- a/src/xml/CMakeLists.txt +++ b/src/xml/CMakeLists.txt @@ -14,6 +14,7 @@ qt_internal_add_module(Xml QT_NO_CONTEXTLESS_CONNECT QT_NO_FOREACH QT_NO_USING_NAMESPACE + QT_USE_NODISCARD_FILE_OPEN LIBRARIES Qt::CorePrivate PUBLIC_LIBRARIES