The function template is constrained in the template-initializer to
only rvalues, therefore this overload is never instantiated for
lvalue.
Amends 79ae79d05c.
Pick-to: 6.7
Change-Id: If0260799fa233eba1ccb3545b9d053496901fc2e
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
(cherry picked from commit 297bc0fb306954dbdf34d80017055b6924315d81)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
The conditional noexcept in comparison operators is known to cause
problems in various cases.
For example, we had a problem in QBAV, where gcc and clang tried to
expand conditional noexcept before the class was complete, and, as a
result, discarded some of the QBAV constructors (see
fff6562f8c for a more detailed
explanation).
Other problem is related to the GHS compiler which tries to compile
the noexcept specification and provides a hard error instead of
SFINAE'ing out in case of failure
(see e1f45ad818 or
0ac0b412c754e53d167716f207be9d76a7fe16be as examples).
This patch reworks the macros to get rid of the conditional noexcept.
Instead, it demands that all operators are noexcept by default, and
adds another set of helper macros that can be used if it's not
possible to make the relational operators noexcept.
The new macros end with the _NON_NOEXCEPT suffix.
The patch also adds static_assert() to the generated operators to
verify that the proper macros are used. However, some platforms
(e.g. QNX and Integrity) fail to handle conditional noexcept on
lambdas, and so we have to use yet another macro to generate the
checks only on platforms that handle them properly.
This patch also applies the new approach to qtbase, adding noexcept
where possible, and falling back to the _NON_NOEXCEPT macros
otherwise.
As a drive-by: fix the macro implementation to use
QtOrderingPrivate::reversed() instead of manually reimplementing it.
I decided to pick the patch to 6.8, because it allows to fix some
questionable APIs (see QBAV story above).
Change-Id: I72f56778acb469f18b578b3418c0c41b4f6d62e7
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
(cherry picked from commit d292648d0bbac50388dae035dc34782accb3807f)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Issue introduced by a68e4f3b96 ("Use the
new QMetaType API in QVariant") in 6.0, which removed the d.is_null
reset at the same time as it replaced the std::destroy_at /
std::construct_at pair with an assignment operation.
[ChangeLog][QtCore][QVariant] Fixed a bug that would allow the class to
keep returning isNull() = true even after calling setValue().
Fixes: QTBUG-125472
Pick-to: 6.5 6.7
Change-Id: If05cb740b64f42eba21efffd17d13f6b1e8113c2
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Christian Ehrlicher <ch.ehrlicher@gmx.de>
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
I added QT_NO_VARIANT to qconfig-bootstrapped.h to be clearer on what
the #ifs are, but there's no testing of that feature outside of
QT_BOOTSTRAPPED.
Change-Id: I01ec3c774d9943adb903fffd17b7e8ac4340fb89
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
The relational operators were removed in
8652c79df0 with the argument that they
do not have a total order. Back than it was a valid argument, because Qt
did not support any of the C++20 ordering types.
Now Qt has its own implementation for all three ordering types, so we
could technically add relational operators and claim that QVariant
provides partial ordering.
However, that could potentially lead to many bugs and/or unexpected
results, if people start using QVariant as a key in std::map/QMap
containers.
We do not want that to happen, so we only use the helper macros to
implement (in)equality operators.
This commit also extends the unit tests, providing more extensive
testing of (in)equality operators and the pre-existing
QVariant::compare() method.
Fixes: QTBUG-113234
Change-Id: I783f3b5df552da782627f4ed0a5bb1b577753a23
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
It appears to be used only in qlalr, which is, however, not
bootstrapped.
Pick-to: 6.7 6.6 6.5 6.2
Change-Id: Idc16d957bf687238c7b0ee603d8b092e2048ef18
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
The QVariant(QMetaType) constructor is a major anti-pattern: unlike
*every* other QVariant's constructor, it doesn't build a QVariant
holding the QMetaType object, but a QVariant of the specified type.
Introduce a named constructor for this use case instead.
In principle, this should lead to a deprecation of the QMetaType
constructor... except that it's used everywhere, so I can't do it at
this time.
Drive-by, improve the documentation of the QVariant(QMetaType)
constructor (since it's basically c&p for the new fromMetaType
function).
[ChangeLog][QtCore][QVariant] Added the QVariant::fromMetaType named
constructor, that builds a QVariant of a given QMetaType.
Change-Id: I4a499526bd0fe98eed0c1a3e91bcfc21efa9e352
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
If we have a rvalue reference to an unshared QVariant, we can avoid
potentially expensive copies, and use move semantics instead.
[ChangeLog][QtCore][QVariant] Added rvalue QVariant overloads of qvariant_cast<T>() and QVariant::value<T>().
[ChangeLog][Potentially Source-Incompatible Changes][QVariant] It is no
longer possible to take the address of a specialization of
qvariant_cast; consider using a lambda function instead.
Change-Id: Ifc74991eadcc31387b755c45484224a3200bb0ba
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Keeps all the special cases in a central place and will help with
adding an rvalue overload of fromValue() for 6.6.
Change-Id: I14f12bb98a2e2f4edfcec8ce39660643e23c1d07
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Extract Method fromStdVariantImpl() to share the otherwise
more-or-less identical implementation between the two overloads.
Don't use a constrained template version of fromStdVariantImpl() as
fromStdVariant(), because the constraint would have to be very complex
to continue allowing subclasses of std::variant to be passed.
As a drive-by, mark the valueless_by_exception() path Q_UNLIKELY.
[ChangeLog][QtCore][QVariant] Added overload of fromStdVariant()
taking rvalue std::variant<>s.
Fixes: QTBUG-114134
Change-Id: Ia1c7ae93ab421e6689dc9f2d8d0c2295b23cbbf6
Reviewed-by: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
When passing an rvalue-reference to QVariant, there is no reason to make
a copy if the type is moveable. Moreover, we know that the pointer which
we construct from the object passed to fromValue non-null. We make use
of both facts by parametrizing custom_construct on
non-nullness and availability of a move-ctor, and then dispatching to
the suitable template.
We need to keep the const T& overload, as otherwise code which
explicitly specializes fromValue and passes a const lvalue to it would
stop to compile.
[ChangeLog][QtCore][QVariant] Added fromValue() overload taking rvalues.
Change-Id: I44fb757d516ef364fe7967bc103b3f98278b4919
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
QDoc mis-interprets the Type and List template arguments as referring
to the QVariant::Type enum and its List enumerator, resp.
To fix, rename the template parameters from Type to T and from List
to U.
Task-number: QTBUG-112187
Change-Id: Ib4093acdd84cc86a0f85dcc5046b6e7da7885a44
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
[ChangeLog][QtCore][QVariant] Implemented in-place construction for
QVariant. The constructor taking std::in_place_type<Type> constructs
an object of type Type directly inside QVariant's storage, without any
further copy or move operations. QVariant::emplace() does the same
when replacing the content of an existing QVariant and tries to reuse
previously-allocated memory.
Fixes: QTBUG-112187
Change-Id: I16614ad701fa3bb583976ed2001bb312f119a51f
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
The use of unqualified fromValue(arg) in the visitor implementation
invites non-QVariant fromValue(T) overloads to be found using ADL,
which just happen to compile because their return value implicitly
converts to QVariant (like most stuff does).
To rule this out, use FQN QVariant::fromValue() to switch off ADL.
[ChangeLog][QtCore][QVariant] The fromStdVariant() function used an
unqualifed fromValue() call to convert each alternative type in the
std::variant. It now uses qualified QVariant::fromValue() to avoid
picking up unrelated fromValue() overloads whose return value just
happens to implicitly convert to QVariant.
Amends 5927acaf65.
Pick-to: 6.5 6.2
Change-Id: Ica21b08c919459d0a740af03f451e4ffe224b641
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Add an empty line between the two.
Pick-to: 6.5
Change-Id: If1c50ebb0b825acc53364cce2e083332367e757c
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Will be re-used in the upcoming emplace() function.
No attempt is made to re-write the expression to be more
readable. That's left for another commit.
Task-number: QTBUG-112187
Change-Id: Id391b78f1477c5225beda8a32c4f6c1393dd51bb
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
Will be re-used in the upcoming emplace() function.
Task-number: QTBUG-112187
Change-Id: Ie2b4570b7ba6c9d0ce938203933758a0d0d59f5a
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This avoids constructing an object just to copy (later: move) it into a
QVariant.
ChangeLog will be in a follow-up change adding emplace support.
Task-number: QTBUG-112187
Change-Id: I444e580c7d8927d41b3d21d5a521e7c475119e4c
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
This second patch of the series implements get().
Unlike other get() implementations in Qt, don't use my trick with the
constrained friend free function here. Instead, provide the four
overloads manually, like mandated by the standard library for
std::variant (and, indeed, tuple), such that these functions can also
be used on subclasses of QVariant.
[ChangeLog][QtCore][QVariant] Implemented the type-based std::variant
access protocol (get<T>()/get_if<T>()) to allow easier access to the
contained element than the previous solution of casting data(), as
well as to allow generic code to treat QVariant and std::variant the
same. The holds_alternative<T>() function is not provided, since it's
the same as get_if<T> != nullptr. The index-based variant access
functions (get<I>()/get_if<I>()) are also not provided, because,
unlike std::variant, QVariant does not have a bounded number of
alternative types, and QMetaType IDs are not (all) compile-time
constants.
Fixes: QTBUG-111598
Change-Id: Id7bc41f7d91761b3483ec5604f1a4685c8079844
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
QVariant supports non-default-constructible payloads, in principle
(QTBUG-105140). And fromValue() works with such types, but value()
insists on providing a wide contract and therefore accidentally
requires default-constructible.
We can now invent other "Qt-ish" API like optional::value_or() or a
value() that returns optional<T>, but we should first get the
interface in that generic code must use, and which at the same time is
the most versatile, because it gives write access to the element
stored in the variant: [variant.get], consisting of get_if(), get(),
and holds_alternative(). The latter is the same as get_if() !=
nullptr, so we won't provide it.
This first patch implements get_if(), adds test for it.
As a Hidden Friend supposed to be called with explicit template
arguments, we run into the problem that wg21.link/P0846 solved for
C++20. Add the usual work-around, and check it works.
The ChangeLog will be on the last patch.
Task-number: QTBUG-111598
Change-Id: I23f57ea2de3946944810c5552c68a7a3060a44f2
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
qIsRelocatable and qIsValueInitializationBitwiseZero are not public API,
hide them away.
Pick-to: 6.5 6.5.0
Change-Id: Ib4eeaab46d01759098e96091b700e9a28fd50962
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
To allow the user to customize the C++ code that QDoc sees, so as to be
able to work-around some limitations on QDoc itself, QDoc defines two
symbols: Q_QDOC and Q_CLANG_QDOC, both of which are "true" during an
entire execution of QDoc.
At a certain point in time, QDoc allowed the user the choice between a
custom C++ parser and a Clang based one.
The Q_QDOC symbol would always be defined while the Q_CLANG_QDOC symbol
would be defined only when the Clang based parser was chosen.
In more recent times, QDoc always uses a Clang based parser, such that
both Q_CLANG_QDOC and Q_QDOC are always defined, making them equivalent.
To avoid using different symbols, and the possible confusion and
fragmentation that derives from it, all usages of Q_CLANG_QDOC are now
replaced by the equivalent usages of Q_QDOC.
Change-Id: I5810abb9ad1016a4c5bbea99acd03381b8514b3f
Reviewed-by: Kai Koehne <kai.koehne@qt.io>
Instead of having that function load those from memory. This allows us
to pass constant expressions in QVariant::Private s constructor
Change-Id: I3859764fed084846bcb0fffd17045ddd62553710
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Even though it's calling a noexcept(false) constructor, we can declare
when it it won't throw and allow the caller to suppress its own
exception handling.
This necessitated splitting the Q_DECLARE_SHARED into its components
because fromValue<QVariant> uses QTypeInfo<QVariant>::isRelocatable.
Change-Id: I3859764fed084846bcb0fffd1704503aa4d3e535
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Group them by noexceptness and then organize each group logically. We
also don't need to #ifdef the constructors for the unavailable classes,
as they are forward-declared.
Change-Id: I6f936da6f6e84d649f70fffd17060903c78edf0f
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
All of those are implicitly-shared Qt data types whose copy constructors
can't throw and have wide contracts (there aren't even any assertions
for validity in any of them). These are all types with a QVariant
implicit constructor, except for QCborValue, which is updated on this
list so QJsonValue (which has a QVariant constructor) is also
legitimately noexcept.
To ensure we haven't made a mistake, the Private constructor checks
again.
Change-Id: I3859764fed084846bcb0fffd17044d8319a45e1f
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Commit 2f0a625fd4 added noexcept for
these, but didn't verify that the operation itself was noexcept. And it
wasn't on 32-bit systems, because sizeof(void *) is only 4 bytes, making
QVariant and QVariant::Private a mere 12 bytes. That's insufficient for
QUuid and for almost all geometric types when qreal==double.
We can't use sizeof() in qvariant.h because most of those classes are
only forward-declared.
Change-Id: I6f936da6f6e84d649f70fffd1705ce948891d06a
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
customConstruct has to do an additional check to ensure that
QVariant::fromValue(nullptr) returns null.
We can get rid of it by special casing nullptr_t in a fromValue overload
instead, reducing the amount of work that needs to happen at runtime.
Change-Id: I2aea6aecfee0a9404cbd78dbea01a1d5d3047ca0
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
QHash, QString, QByteArray, and QDateTime are explicitly noexcept, while
QList, QMap, and QModelIndex are implicitly noexcept because all their
members are explicitly nothrow-copyable.
There are a couple more Qt types that ought to be nothrow-copyable too,
like QBitArray and QUrl.
Change-Id: I3859764fed084846bcb0fffd17044b5ebb046ee9
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Make them all noexcept and ensure they are all passed by value.
Unfortunately for QRectF and QLineF, they're too big when qreal==double,
so QVariant needs to allocate memory itself. Strictly speaking, they're
too big for passing by value too, but the codegen is identical, so we
may as well. For Qt 7, enlarging QVariant::Private would be a good idea.
Change-Id: I3859764fed084846bcb0fffd17044ac379b3c1d2
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Lars Knoll <lars.knoll@gmail.com>
With very minor code style fixes. Moved up so they can be used in some
methods below.
Change-Id: I3859764fed084846bcb0fffd17044f8e61886e2c
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
They don't need to be in the header. They're still inline though.
Change-Id: I3859764fed084846bcb0fffd17044f49031feefc
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
And move it into the .cpp file, to hide the ugliness.
Change-Id: I3859764fed084846bcb0fffd17044729e361a42e
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
It's effectively the same and no one is using v_construct().
Change-Id: I3859764fed084846bcb0fffd1704470801c9e6e7
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
They're ALWAYS const objects, though they also chock full of relocations
so they are never in read-only sections of memory (except maybe in final
executables that are position-dependent).
These are methods in a private sub-class of QVariant. No one outside of
QtCore (at least qtbase) should be using them directly. QVariant doesn't
have many friends (a bit anti-social); the one that matters is
qvariant_cast and that one does access QVariant::Private. This is not a
BC problem because QVariant::Private::type()'s signature is not
changing. In any case, QVariant's Q_CORE_EXPORT does not apply to
QVariant::Private anyway (see [1]).
[1] https://msvc.godbolt.org/z/r9cer8eWh
Pick-to: 6.3 6.4
Change-Id: I3859764fed084846bcb0fffd17035355f823dc8f
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Replace the current license disclaimer in files by
a SPDX-License-Identifier.
Files that have to be modified by hand are modified.
License files are organized under LICENSES directory.
Task-number: QTBUG-67283
Change-Id: Id880c92784c40f3bbde861c0d93f58151c18b9f1
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Reviewed-by: Jörg Bornemann <joerg.bornemann@qt.io>
The QVariant(bool) is an extremely dangerous catch-all for all sorts of
things that may convert to bool, including arbitrary pointers. Delete
the corresponding constructor, in order to force users to use the
(correct) construction using fromValue, and/or to prevent bugs
altogether. This is technically speaking a SiC, but one of type A -- if
pointer to bool was intented, just do the conversion explicitly.
[ChangeLog][QtCore][QVariant] QVariant used to be constructible by raw
pointers through a conversion towards bool. This is now illegal. If such
a conversion is needed, users are advised to insert manual casts to
bool.
Change-Id: I1b1f81962259514e57d841246740e0f7050104e0
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Forward declare more types in qvariant.h, and do the same for qdebug.h
(which will be removed from qvariant in a separate patch).
As we now only forward declare containers (e.g. QMap, QList, ...), code
which includes <QVariantMap>, <QVariantList>... breaks without further
adjustment: So far, those headers simply included qvariant.h. However,
by introducing new actual headers for those types and adjusting
sync.profile, we can avoid this issue.
To avoid breaking leaf modules and user code, we make the change opt-in:
Unless QT_LEAN_HEADERS is defined to a value of >= 1, we still
include the superfluous headers. We also set this macro in qtbase via
QT_EXTRA_INTERNAL_TARGET_DEFINES.
[ChangeLog][Potentially Source-Incompatible Changes] qvariant.h no
longer includes <QList>, <QMap>, <QHash>, <QVarLengthArray>, <QSet> and
<QObject>. Code that relied on transitive includes might need to
explicitly include those headers now. Notably, including <QVariant> (or
qvariant.h) is no longer sufficient when using QVariant(List|Map|Hash).
Using them now requires including respectively <QVariantList>,
<QVariantMap>, or <QVariantHash>. Alternatively, including <QVariant>
and the <QList>, <QMap> or <QHash> header also works.
[ChangeLog][Potentially Source-Incompatible Changes] qdebug.h no longer
includes <QSet>, <QHash>, <QVarLengthArray> and <QMap>. Code that relied
on transitive includes might need to explicitly include those headers
now.
Task-number: QTBUG-97601
Change-Id: I142e5de709ed0b305716369a3266389ab7fbbb71
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
This header is a C++17 feature that is already used unconditionally
in qtypeinfo.h.
Change-Id: I26330d298e95102f3e94c0c69fc95c1025666eb4
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Qt requires a compiler that support C++17 thus __cplusplus
is always 201703L or higher. This patch removes checks
for __cplusplus value that always succeed.
Change-Id: I4b830683ecefab8f913d8b09604086d53209d2e3
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
There is no reason for QVariant to go through QMetaType when it can use
the QMetaTypeInterface directly. Without LTO, the QMetaType method calls
are opaque, and we therefore risk to lose optimizations.
Additionally, avoid constructing a QMetaType from a type id if we
already have the QMetaType.
Fixes: QTBUG-90673
Change-Id: I7069ff6aff70d5baecdf5cf5760014c3dda81784
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>