summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@qt.io>2023-09-12 23:54:00 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2023-09-15 09:43:53 +0000
commita1a5e12ef908e900a0ec600cd1904e797fcab9c4 (patch)
treeba3ee89ecd7fea2713505259faa486a9cf10e71f
parent5866056a9707c9bd6865154c5e5613b0fd214420 (diff)
Long live Q_(U)INT128_MIN/MAX!
Since compilers don't provide such macros, do it ourselves. In order to test these macros, add ad-hoc specializations of QTest::toString() for qint128 and quint128 locally to the test. Turns out it's not too hard to write them, so we might move them to a public header, yet. Change-Id: I1483f3af2ccec6038e1c780649f9ffe413bb59ef Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> (cherry picked from commit 104a0a9ecdb18d65e4d9075d87e8860c6c9d8335) (cherry picked from commit 09bf722590ca6d1482b6605e1dffaaadd863e125) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
-rw-r--r--src/corelib/global/qtypes.cpp51
-rw-r--r--src/corelib/global/qtypes.h15
-rw-r--r--tests/auto/corelib/global/qglobal/qglobal.c6
-rw-r--r--tests/auto/corelib/global/qglobal/tst_qglobal.cpp68
4 files changed, 135 insertions, 5 deletions
diff --git a/src/corelib/global/qtypes.cpp b/src/corelib/global/qtypes.cpp
index f13bf6cdff..507fd6bbde 100644
--- a/src/corelib/global/qtypes.cpp
+++ b/src/corelib/global/qtypes.cpp
@@ -152,7 +152,7 @@ QT_BEGIN_NAMESPACE
Typedef for \c{__int128} on platforms that support it (Qt defines the macro
\l QT_SUPPORTS_INT128 if this is the case).
- \sa quint128, QT_SUPPORTS_INT128
+ \sa Q_INT128_MIN, Q_INT128_MAX, quint128, QT_SUPPORTS_INT128
*/
/*!
@@ -163,7 +163,7 @@ QT_BEGIN_NAMESPACE
Typedef for \c{unsigned __int128} on platforms that support it (Qt defines
the macro \l QT_SUPPORTS_INT128 if this is the case).
- \sa qint128, QT_SUPPORTS_INT128
+ \sa Q_UINT128_MAX, qint128, QT_SUPPORTS_INT128
*/
/*!
@@ -174,7 +174,7 @@ QT_BEGIN_NAMESPACE
Qt defines this macro as well as the \l qint128 and \l quint128 types if
the platform has support for 128-bit integer types.
- \sa qint128, quint128
+ \sa qint128, quint128, Q_INT128_MIN, Q_INT128_MAX, Q_UINT128_MAX
*/
/*!
@@ -376,6 +376,48 @@ QT_BEGIN_NAMESPACE
\sa quint64, Q_INT64_C()
*/
+/*!
+ \macro Q_UINT128_MAX
+ \relates <QtTypes>
+ \since 6.6
+
+ This macro expands to a compile-time constant representing the
+ maximum value representable in a \l quint128.
+
+ This macro is available in both C++ and C modes.
+
+ The minimum of \l quint128 is 0 (zero), so a \c{Q_UINT128_MIN} is neither
+ needed nor provided.
+
+ \sa Q_INT128_MAX, quint128, QT_SUPPORTS_INT128
+*/
+
+/*!
+ \macro Q_INT128_MIN
+ \relates <QtTypes>
+ \since 6.6
+
+ This macro expands to a compile-time constant representing the
+ minimum value representable in a \l qint128.
+
+ This macro is available in both C++ and C modes.
+
+ \sa Q_INT128_MAX, qint128, QT_SUPPORTS_INT128
+*/
+
+/*!
+ \macro Q_INT128_MAX
+ \relates <QtTypes>
+ \since 6.6
+
+ This macro expands to a compile-time constant representing the
+ maximum value representable in a \l qint128.
+
+ This macro is available in both C++ and C modes.
+
+ \sa Q_INT128_MIN, Q_UINT128_MAX, qint128, QT_SUPPORTS_INT128
+*/
+
// Statically check assumptions about the environment we're running
// in. The idea here is to error or warn if otherwise implicit Qt
// assumptions are not fulfilled on new hardware or compilers
@@ -439,9 +481,10 @@ static_assert(sizeof(qint128) == 16, "Internal error, qint128 is misdefined");
#ifdef QT_SUPPORTS_INT128
// check that numeric_limits works:
// This fails here for GCC 9, but succeeds on Clang and GCC >= 11
+// However, all tests in tst_qglobal::int128Literals() pass for GCC 9, too,
// so just suppress the check for older GCC:
# if !defined(Q_CC_GNU_ONLY) || Q_CC_GNU >= 1100
-static_assert(std::numeric_limits<quint128>::max() == quint128(-1));
+static_assert(std::numeric_limits<quint128>::max() == Q_UINT128_MAX);
# endif
#endif
diff --git a/src/corelib/global/qtypes.h b/src/corelib/global/qtypes.h
index 6a4b6acf39..cca2263901 100644
--- a/src/corelib/global/qtypes.h
+++ b/src/corelib/global/qtypes.h
@@ -67,7 +67,20 @@ typedef quint64 qulonglong;
#if defined(QT_SUPPORTS_INT128)
__extension__ typedef __int128_t qint128;
__extension__ typedef __uint128_t quint128;
-#endif
+
+// limits:
+# ifdef __cplusplus /* need to avoid c-style-casts in C++ mode */
+# define QT_C_STYLE_CAST(type, x) static_cast<type>(x)
+# else /* but C doesn't have constructor-style casts */
+# define QT_C_STYLE_CAST(type, x) ((type)x)
+# endif
+# ifndef Q_UINT128_MAX /* allow qcompilerdetection.h/user override */
+# define Q_UINT128_MAX QT_C_STYLE_CAST(quint128, -1)
+# endif
+# define Q_INT128_MAX QT_C_STYLE_CAST(qint128, (Q_UINT128_MAX / 2))
+# define Q_INT128_MIN (-Q_INT128_MAX - 1)
+
+#endif // QT_SUPPORTS_INT128
#ifndef __cplusplus
// In C++ mode, we define below using QIntegerForSize template
diff --git a/tests/auto/corelib/global/qglobal/qglobal.c b/tests/auto/corelib/global/qglobal/qglobal.c
index bf6d19cb81..5817d6cacb 100644
--- a/tests/auto/corelib/global/qglobal/qglobal.c
+++ b/tests/auto/corelib/global/qglobal/qglobal.c
@@ -53,6 +53,12 @@ void tst_GlobalTypes()
#endif /* QT_SUPPORTS_INT128 */
}
+#if QT_SUPPORTS_INT128
+qint128 tst_qint128_min() { return Q_INT128_MIN + 0; }
+qint128 tst_qint128_max() { return 0 + Q_INT128_MAX; }
+quint128 tst_quint128_max() { return Q_UINT128_MAX - 1 + 1; }
+#endif
+
/* Qt version */
int tst_QtVersion()
{
diff --git a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp
index 33be8fd0a2..edfa59ebf1 100644
--- a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp
+++ b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp
@@ -10,8 +10,49 @@
#include <QString>
#include <QtVersion>
+#include <array>
#include <cmath>
+QT_BEGIN_NAMESPACE
+namespace QTest {
+#ifdef QT_SUPPORTS_INT128
+namespace detail {
+ char *i128ToStringHelper(std::array<char, 64> &buffer, quint128 n)
+ {
+ auto dst = buffer.data() + buffer.size();
+ *--dst = '\0'; // NUL-terminate
+ if (n == 0) {
+ *--dst = '0'; // and done
+ } else {
+ while (n != 0) {
+ *--dst = "0123456789"[n % 10];
+ n /= 10;
+ }
+ }
+ return dst;
+ }
+}
+template <>
+char *toString(const qint128 &i)
+{
+ if (i == std::numeric_limits<qint128>::min()) // -i is not representable, hardcode:
+ return qstrdup("-170141183460469231731687303715884105728");
+ std::array<char, 64> buffer;
+ auto dst = detail::i128ToStringHelper(buffer, i < 0 ? -i : i);
+ if (i < 0)
+ *--dst = '-';
+ return qstrdup(dst);
+}
+template <>
+char *toString(const quint128 &i)
+{
+ std::array<char, 64> buffer;
+ return qstrdup(detail::i128ToStringHelper(buffer, i));
+}
+#endif // QT_SUPPORTS_INT128
+} // namespace QTest
+QT_END_NAMESPACE
+
class tst_QGlobal: public QObject
{
Q_OBJECT
@@ -28,6 +69,7 @@ private slots:
void qCoreAppStartupFunction();
void qCoreAppStartupFunctionRestart();
void integerForSize();
+ void int128Literals();
void buildAbiEndianness();
void testqOverload();
void testqMinMax();
@@ -44,6 +86,12 @@ extern "C" { // functions in qglobal.c
void tst_GlobalTypes();
int tst_QtVersion();
const char *tst_qVersion();
+#if QT_SUPPORTS_INT128
+qint128 tst_qint128_min();
+qint128 tst_qint128_max();
+quint128 tst_quint128_max();
+#endif
+
}
void tst_QGlobal::cMode()
@@ -435,6 +483,26 @@ void tst_QGlobal::integerForSize()
#endif
}
+void tst_QGlobal::int128Literals()
+{
+#ifdef QT_SUPPORTS_INT128
+#define COMPARE_EQ(lhs, rhs, Expected128) do { \
+ constexpr auto lhs_ = lhs; \
+ static_assert(std::is_same_v<std::remove_cv_t<decltype(lhs_)>, Expected128>); \
+ QCOMPARE_EQ(lhs_, rhs); \
+ } while (0)
+ COMPARE_EQ(Q_INT128_MIN, std::numeric_limits<qint128>::min(), qint128);
+ COMPARE_EQ(Q_INT128_MAX, std::numeric_limits<qint128>::max(), qint128);
+ COMPARE_EQ(Q_UINT128_MAX, std::numeric_limits<quint128>::max(), quint128);
+ QCOMPARE_EQ(tst_qint128_min(), Q_INT128_MIN);
+ QCOMPARE_EQ(tst_qint128_max(), Q_INT128_MAX);
+ QCOMPARE_EQ(tst_quint128_max(), Q_UINT128_MAX);
+#undef COMPARE_EQ
+#else
+ QSKIP("This test requires 128-bit integer support enabled in the compiler.");
+#endif
+}
+
typedef QPair<const char *, const char *> stringpair;
Q_DECLARE_METATYPE(stringpair)