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>
This commit is contained in:
parent
5866056a97
commit
a1a5e12ef9
@ -152,7 +152,7 @@ QT_BEGIN_NAMESPACE
|
|||||||
Typedef for \c{__int128} on platforms that support it (Qt defines the macro
|
Typedef for \c{__int128} on platforms that support it (Qt defines the macro
|
||||||
\l QT_SUPPORTS_INT128 if this is the case).
|
\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
|
Typedef for \c{unsigned __int128} on platforms that support it (Qt defines
|
||||||
the macro \l QT_SUPPORTS_INT128 if this is the case).
|
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
|
Qt defines this macro as well as the \l qint128 and \l quint128 types if
|
||||||
the platform has support for 128-bit integer types.
|
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()
|
\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
|
// Statically check assumptions about the environment we're running
|
||||||
// in. The idea here is to error or warn if otherwise implicit Qt
|
// in. The idea here is to error or warn if otherwise implicit Qt
|
||||||
// assumptions are not fulfilled on new hardware or compilers
|
// 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
|
#ifdef QT_SUPPORTS_INT128
|
||||||
// check that numeric_limits works:
|
// check that numeric_limits works:
|
||||||
// This fails here for GCC 9, but succeeds on Clang and GCC >= 11
|
// 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:
|
// so just suppress the check for older GCC:
|
||||||
# if !defined(Q_CC_GNU_ONLY) || Q_CC_GNU >= 1100
|
# 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
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -67,7 +67,20 @@ typedef quint64 qulonglong;
|
|||||||
#if defined(QT_SUPPORTS_INT128)
|
#if defined(QT_SUPPORTS_INT128)
|
||||||
__extension__ typedef __int128_t qint128;
|
__extension__ typedef __int128_t qint128;
|
||||||
__extension__ typedef __uint128_t quint128;
|
__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
|
#ifndef __cplusplus
|
||||||
// In C++ mode, we define below using QIntegerForSize template
|
// In C++ mode, we define below using QIntegerForSize template
|
||||||
|
@ -53,6 +53,12 @@ void tst_GlobalTypes()
|
|||||||
#endif /* QT_SUPPORTS_INT128 */
|
#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 */
|
/* Qt version */
|
||||||
int tst_QtVersion()
|
int tst_QtVersion()
|
||||||
{
|
{
|
||||||
|
@ -10,8 +10,49 @@
|
|||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QtVersion>
|
#include <QtVersion>
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <cmath>
|
#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
|
class tst_QGlobal: public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -28,6 +69,7 @@ private slots:
|
|||||||
void qCoreAppStartupFunction();
|
void qCoreAppStartupFunction();
|
||||||
void qCoreAppStartupFunctionRestart();
|
void qCoreAppStartupFunctionRestart();
|
||||||
void integerForSize();
|
void integerForSize();
|
||||||
|
void int128Literals();
|
||||||
void buildAbiEndianness();
|
void buildAbiEndianness();
|
||||||
void testqOverload();
|
void testqOverload();
|
||||||
void testqMinMax();
|
void testqMinMax();
|
||||||
@ -44,6 +86,12 @@ extern "C" { // functions in qglobal.c
|
|||||||
void tst_GlobalTypes();
|
void tst_GlobalTypes();
|
||||||
int tst_QtVersion();
|
int tst_QtVersion();
|
||||||
const char *tst_qVersion();
|
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()
|
void tst_QGlobal::cMode()
|
||||||
@ -435,6 +483,26 @@ void tst_QGlobal::integerForSize()
|
|||||||
#endif
|
#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;
|
typedef QPair<const char *, const char *> stringpair;
|
||||||
Q_DECLARE_METATYPE(stringpair)
|
Q_DECLARE_METATYPE(stringpair)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user