summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2022-11-03 22:14:39 -0700
committerThiago Macieira <thiago.macieira@intel.com>2022-11-09 04:05:50 -0700
commitcf0a1c2e5165a8e8cc05dff0092857942cf06331 (patch)
tree86e193b810aa8ef30e83273be4155f3c5c25695c /src/corelib/kernel
parentda6efbb12b8ace783c8dcc8e43c34c7269410829 (diff)
QVariant: fix comparison of enums to numerics
qIsNumericType does not return true for enum types, which meant we never called numericCompare() or numericEquals() when one of the types was an enum. Task-number: QTBUG-108188 Change-Id: I3d74c753055744deb8acfffd172449c68af19367 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r--src/corelib/kernel/qvariant.cpp42
1 files changed, 38 insertions, 4 deletions
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index 91a17335fd..9fb30c6f28 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -2158,15 +2158,49 @@ static bool qIsFloatingPoint(uint tp)
return tp == QMetaType::Double || tp == QMetaType::Float;
}
+static bool canBeNumericallyCompared(const QtPrivate::QMetaTypeInterface *iface1,
+ const QtPrivate::QMetaTypeInterface *iface2)
+{
+ if (!iface1 || !iface2)
+ return false;
+
+ // We don't need QMetaType::id() here because the type Id is always stored
+ // directly for all built-in types.
+ bool isNumeric1 = qIsNumericType(iface1->typeId);
+ bool isNumeric2 = qIsNumericType(iface2->typeId);
+
+ // if they're both numeric (or QString), then they can be compared
+ if (isNumeric1 && isNumeric2)
+ return true;
+
+ bool isEnum1 = iface1->flags & QMetaType::IsEnumeration;
+ bool isEnum2 = iface2->flags & QMetaType::IsEnumeration;
+
+ // if both are enums, we can only compare if they are the same enum
+ // (the language does allow comparing two different enum types, but that's
+ // usually considered poor coding and produces a warning)
+ if (isEnum1 && isEnum2)
+ return QMetaType(iface1) == QMetaType(iface2);
+
+ // if one is an enum and the other is a numeric, we can compare too
+ if (isEnum1 && isNumeric2)
+ return true;
+ if (isNumeric1 && isEnum2)
+ return true;
+
+ // we need at least one enum and one numeric...
+ return false;
+}
+
static int numericTypePromotion(const QtPrivate::QMetaTypeInterface *iface1,
const QtPrivate::QMetaTypeInterface *iface2)
{
+ Q_ASSERT(canBeNumericallyCompared(iface1, iface2));
+
// We don't need QMetaType::id() here because the type Id is always stored
// directly for the types we're comparing against below.
uint t1 = iface1->typeId;
uint t2 = iface2->typeId;
- Q_ASSERT(qIsNumericType(t1));
- Q_ASSERT(qIsNumericType(t2));
if ((t1 == QMetaType::Bool && t2 == QMetaType::QString) ||
(t2 == QMetaType::Bool && t1 == QMetaType::QString))
@@ -2295,7 +2329,7 @@ bool QVariant::equals(const QVariant &v) const
if (metatype != v.metaType()) {
// try numeric comparisons, with C++ type promotion rules (no conversion)
- if (qIsNumericType(metatype.id()) && qIsNumericType(v.d.type().id()))
+ if (canBeNumericallyCompared(metatype.iface(), v.d.type().iface()))
return numericCompare(&d, &v.d) == QPartialOrdering::Equivalent;
#ifndef QT_BOOTSTRAPPED
// if both types are related pointers to QObjects, check if they point to the same object
@@ -2339,7 +2373,7 @@ QPartialOrdering QVariant::compare(const QVariant &lhs, const QVariant &rhs)
QMetaType t = lhs.d.type();
if (t != rhs.d.type()) {
// try numeric comparisons, with C++ type promotion rules (no conversion)
- if (qIsNumericType(lhs.d.type().id()) && qIsNumericType(rhs.d.type().id()))
+ if (canBeNumericallyCompared(lhs.d.type().iface(), rhs.d.type().iface()))
return numericCompare(&lhs.d, &rhs.d);
#ifndef QT_BOOTSTRAPPED
if (canConvertMetaObject(lhs.metaType(), rhs.metaType()))