diff options
Diffstat (limited to 'src/corelib/global/qtypes.cpp')
-rw-r--r-- | src/corelib/global/qtypes.cpp | 528 |
1 files changed, 528 insertions, 0 deletions
diff --git a/src/corelib/global/qtypes.cpp b/src/corelib/global/qtypes.cpp new file mode 100644 index 0000000000..9de3960e2f --- /dev/null +++ b/src/corelib/global/qtypes.cpp @@ -0,0 +1,528 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// Copyright (C) 2022 Intel Corporation. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qtypes.h" + +#include <QtCore/qcompilerdetection.h> +#include <QtCore/qsystemdetection.h> +#include <QtCore/qprocessordetection.h> + +#include <climits> +#include <limits> +#include <type_traits> + +QT_BEGIN_NAMESPACE + +/*! + \headerfile <QtTypes> + \inmodule QtCore + \title Qt Type Declarations + + \brief The <QtTypes> header file includes Qt fundamental type declarations. + + The header file declares several type definitions that guarantee a + specified bit-size on all platforms supported by Qt for various + basic types, for example \l qint8 which is a signed char + guaranteed to be 8-bit on all platforms supported by Qt. The + header file also declares the \l qlonglong type definition for + \c {long long int}. + + Several convenience type definitions are declared: \l qreal for \c + double or \c float, \l uchar for \c {unsigned char}, \l uint for + \c {unsigned int}, \l ulong for \c {unsigned long} and \l ushort + for \c {unsigned short}. + + The header also provides series of macros that make it possible to print + some Qt type aliases (qsizetype, qintptr, etc.) via a formatted output + facility such as printf() or qDebug() without raising formatting warnings + and without the need of a type cast. +*/ + +/*! + \typedef qreal + \relates <QtTypes> + + Typedef for \c double unless Qt is configured with the + \c{-qreal float} option. +*/ + +/*! \typedef uchar + \relates <QtTypes> + + Convenience typedef for \c{unsigned char}. +*/ + +/*! \typedef ushort + \relates <QtTypes> + + Convenience typedef for \c{unsigned short}. +*/ + +/*! \typedef uint + \relates <QtTypes> + + Convenience typedef for \c{unsigned int}. +*/ + +/*! \typedef ulong + \relates <QtTypes> + + Convenience typedef for \c{unsigned long}. +*/ + +/*! \typedef qint8 + \relates <QtTypes> + + Typedef for \c{signed char}. This type is guaranteed to be 8-bit + on all platforms supported by Qt. +*/ + +/*! + \typedef quint8 + \relates <QtTypes> + + Typedef for \c{unsigned char}. This type is guaranteed to + be 8-bit on all platforms supported by Qt. +*/ + +/*! \typedef qint16 + \relates <QtTypes> + + Typedef for \c{signed short}. This type is guaranteed to be + 16-bit on all platforms supported by Qt. +*/ + +/*! + \typedef quint16 + \relates <QtTypes> + + Typedef for \c{unsigned short}. This type is guaranteed to + be 16-bit on all platforms supported by Qt. +*/ + +/*! \typedef qint32 + \relates <QtTypes> + + Typedef for \c{signed int}. This type is guaranteed to be 32-bit + on all platforms supported by Qt. +*/ + +/*! + \typedef quint32 + \relates <QtTypes> + + Typedef for \c{unsigned int}. This type is guaranteed to + be 32-bit on all platforms supported by Qt. +*/ + +/*! \typedef qint64 + \relates <QtTypes> + + Typedef for \c{long long int}. This type is guaranteed to be 64-bit + on all platforms supported by Qt. + + Literals of this type can be created using the Q_INT64_C() macro: + + \snippet code/src_corelib_global_qglobal.cpp 5 + + \sa Q_INT64_C(), quint64, qlonglong +*/ + +/*! + \typedef quint64 + \relates <QtTypes> + + Typedef for \c{unsigned long long int}. This type is guaranteed to + be 64-bit on all platforms supported by Qt. + + Literals of this type can be created using the Q_UINT64_C() + macro: + + \snippet code/src_corelib_global_qglobal.cpp 6 + + \sa Q_UINT64_C(), qint64, qulonglong +*/ + +/*! + \typedef qint128 + \relates <QtTypes> + \since 6.6 + + Typedef for \c{__int128} on platforms that support it (Qt defines the macro + \l QT_SUPPORTS_INT128 if this is the case). + + Literals of this type can be created using the Q_INT128_C() macro. + + \sa Q_INT128_C(), Q_INT128_MIN, Q_INT128_MAX, quint128, QT_SUPPORTS_INT128 +*/ + +/*! + \typedef quint128 + \relates <QtTypes> + \since 6.6 + + Typedef for \c{unsigned __int128} on platforms that support it (Qt defines + the macro \l QT_SUPPORTS_INT128 if this is the case). + + Literals of this type can be created using the Q_UINT128_C() macro. + + \sa Q_UINT128_C(), Q_UINT128_MAX, qint128, QT_SUPPORTS_INT128 +*/ + +/*! + \macro QT_SUPPORTS_INT128 + \relates <QtTypes> + \since 6.6 + + 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, Q_INT128_C(), Q_UINT128_C(), Q_INT128_MIN, Q_INT128_MAX, Q_UINT128_MAX +*/ + +/*! + \typedef qintptr + \relates <QtTypes> + + Integral type for representing pointers in a signed integer (useful for + hashing, etc.). + + Typedef for either qint32 or qint64. This type is guaranteed to + be the same size as a pointer on all platforms supported by Qt. On + a system with 32-bit pointers, qintptr is a typedef for qint32; + on a system with 64-bit pointers, qintptr is a typedef for + qint64. + + Note that qintptr is signed. Use quintptr for unsigned values. + + In order to print values of this type by using formatted-output + facilities such as \c{printf()}, qDebug(), QString::asprintf() and + so on, you can use the \c{PRIdQINTPTR} and \c{PRIiQINTPTR} + macros as format specifiers. They will both print the value as a + base 10 number. + + \code + qintptr p = 123; + printf("The pointer is %" PRIdQINTPTR "\n", p); + \endcode + + \sa qptrdiff, qint32, qint64 +*/ + +/*! \typedef qlonglong + \relates <QtTypes> + + Typedef for \c{long long int} (\c __int64 on Windows). This is + the same as \l qint64. + + \sa qulonglong, qint64 +*/ + +/*! + \typedef qulonglong + \relates <QtTypes> + + Typedef for \c{unsigned long long int} (\c{unsigned __int64} on + Windows). This is the same as \l quint64. + + \sa quint64, qlonglong +*/ + +/*! + \macro PRIdQINTPTR + \macro PRIiQINTPTR + \since 6.2 + \relates <QtTypes> + + See \l qintptr. +*/ + +/*! + \typedef quintptr + \relates <QtTypes> + + Integral type for representing pointers in an unsigned integer (useful for + hashing, etc.). + + Typedef for either quint32 or quint64. This type is guaranteed to + be the same size as a pointer on all platforms supported by Qt. On + a system with 32-bit pointers, quintptr is a typedef for quint32; + on a system with 64-bit pointers, quintptr is a typedef for + quint64. + + Note that quintptr is unsigned. Use qptrdiff for signed values. + + In order to print values of this type by using formatted-output + facilities such as \c{printf()}, qDebug(), QString::asprintf() and + so on, you can use the following macros as format specifiers: + + \list + \li \c{PRIuQUINTPTR}: prints the value as a base 10 number. + \li \c{PRIoQUINTPTR}: prints the value as a base 8 number. + \li \c{PRIxQUINTPTR}: prints the value as a base 16 number, using lowercase \c{a-f} letters. + \li \c{PRIXQUINTPTR}: prints the value as a base 16 number, using uppercase \c{A-F} letters. + \endlist + + \code + quintptr p = 123u; + printf("The pointer value is 0x%" PRIXQUINTPTR "\n", p); + \endcode + + \sa qptrdiff, quint32, quint64 +*/ + +/*! + \macro PRIoQUINTPTR + \macro PRIuQUINTPTR + \macro PRIxQUINTPTR + \macro PRIXQUINTPTR + \since 6.2 + \relates <QtTypes> + + See quintptr. +*/ + +/*! + \typedef qptrdiff + \relates <QtTypes> + + Integral type for representing pointer differences. + + Typedef for either qint32 or qint64. This type is guaranteed to be + the same size as a pointer on all platforms supported by Qt. On a + system with 32-bit pointers, quintptr is a typedef for quint32; on + a system with 64-bit pointers, quintptr is a typedef for quint64. + + Note that qptrdiff is signed. Use quintptr for unsigned values. + + In order to print values of this type by using formatted-output + facilities such as \c{printf()}, qDebug(), QString::asprintf() and + so on, you can use the \c{PRIdQPTRDIFF} and \c{PRIiQPTRDIFF} + macros as format specifiers. They will both print the value as a + base 10 number. + + \code + qptrdiff d = 123; + printf("The difference is %" PRIdQPTRDIFF "\n", d); + \endcode + + \sa quintptr, qint32, qint64 +*/ + +/*! + \macro PRIdQPTRDIFF + \macro PRIiQPTRDIFF + \since 6.2 + \relates <QtTypes> + + See qptrdiff. +*/ + +/*! + \typedef qsizetype + \relates <QtTypes> + \since 5.10 + + Integral type providing Posix' \c ssize_t for all platforms. + + This type is guaranteed to be the same size as a \c size_t on all + platforms supported by Qt. + + Note that qsizetype is signed. Use \c size_t for unsigned values. + + In order to print values of this type by using formatted-output + facilities such as \c{printf()}, qDebug(), QString::asprintf() and + so on, you can use the \c{PRIdQSIZETYPE} and \c{PRIiQSIZETYPE} + macros as format specifiers. They will both print the value as a + base 10 number. + + \code + qsizetype s = 123; + printf("The size is %" PRIdQSIZETYPE "\n", s); + \endcode + + \sa qptrdiff +*/ + +/*! + \macro PRIdQSIZETYPE + \macro PRIiQSIZETYPE + \since 6.2 + \relates <QtTypes> + + See qsizetype. +*/ + +/*! \macro qint64 Q_INT64_C(literal) + \relates <QtTypes> + + Wraps the signed 64-bit integer \a literal in a + platform-independent way. + + Example: + + \snippet code/src_corelib_global_qglobal.cpp 8 + + \sa qint64, Q_UINT64_C(), Q_INT128_C() +*/ + +/*! \macro quint64 Q_UINT64_C(literal) + \relates <QtTypes> + + Wraps the unsigned 64-bit integer \a literal in a + platform-independent way. + + Example: + + \snippet code/src_corelib_global_qglobal.cpp 9 + + \sa quint64, Q_INT64_C(), Q_UINT128_C() +*/ + +/*! + \macro qint128 Q_INT128_C(literal) + \relates <QtTypes> + \since 6.6 + + Wraps the signed 128-bit integer \a literal in a + platform-independent way. + + \note Unlike Q_INT64_C(), this macro is only available in C++, not in C. + This is because compilers do not provide these literals as built-ins and C + does not have support for user-defined literals. + + \sa qint128, Q_UINT128_C(), Q_INT128_MIN, Q_INT128_MAX, Q_INT64_C(), QT_SUPPORTS_INT128 +*/ + +/*! + \macro quint128 Q_UINT128_C(literal) + \relates <QtTypes> + \since 6.6 + + Wraps the unsigned 128-bit integer \a literal in a + platform-independent way. + + \note Unlike Q_UINT64_C(), this macro is only available in C++, not in C. + This is because compilers do not provide these literals as built-ins and C + does not have support for user-defined literals. + + \sa quint128, Q_INT128_C(), Q_UINT128_MAX, Q_UINT64_C(), QT_SUPPORTS_INT128 +*/ + +/*! + \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, Q_UINT128_C, 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, Q_INT128_C, 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, Q_INT128_C, 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 +// (if this list becomes too long, consider factoring into a separate file) +static_assert(UCHAR_MAX == 255, "Qt assumes that char is 8 bits"); +static_assert(sizeof(int) == 4, "Qt assumes that int is 32 bits"); +static_assert(QT_POINTER_SIZE == sizeof(void *), "QT_POINTER_SIZE defined incorrectly"); +static_assert(sizeof(float) == 4, "Qt assumes that float is 32 bits"); +static_assert(sizeof(char16_t) == 2, "Qt assumes that char16_t is 16 bits"); +static_assert(sizeof(char32_t) == 4, "Qt assumes that char32_t is 32 bits"); +#if defined(Q_OS_WIN) +static_assert(sizeof(wchar_t) == sizeof(char16_t)); +#endif +static_assert(std::numeric_limits<int>::radix == 2, + "Qt assumes binary integers"); +static_assert((std::numeric_limits<int>::max() + std::numeric_limits<int>::lowest()) == -1, + "Qt assumes two's complement integers"); +static_assert(sizeof(wchar_t) == sizeof(char32_t) || sizeof(wchar_t) == sizeof(char16_t), + "Qt assumes wchar_t is compatible with either char32_t or char16_t"); + +// While we'd like to check for __STDC_IEC_559__, as per ISO/IEC 9899:2011 +// Annex F (C11, normative for C++11), there are a few corner cases regarding +// denormals where GHS compiler is relying hardware behavior that is not IEC +// 559 compliant. So split the check in several subchecks. + +// On GHS the compiler reports std::numeric_limits<float>::is_iec559 as false. +// This is all right according to our needs. +#if !defined(Q_CC_GHS) +static_assert(std::numeric_limits<float>::is_iec559, + "Qt assumes IEEE 754 floating point"); +#endif + +// Technically, presence of NaN and infinities are implied from the above check, +// but double checking our environment doesn't hurt... +static_assert(std::numeric_limits<float>::has_infinity && + std::numeric_limits<float>::has_quiet_NaN, + "Qt assumes IEEE 754 floating point"); + +// is_iec559 checks for ISO/IEC/IEEE 60559:2011 (aka IEEE 754-2008) compliance, +// but that allows for a non-binary radix. We need to recheck that. +// Note how __STDC_IEC_559__ would instead check for IEC 60559:1989, aka +// ANSI/IEEE 754−1985, which specifically implies binary floating point numbers. +static_assert(std::numeric_limits<float>::radix == 2, + "Qt assumes binary IEEE 754 floating point"); + +// not required by the definition of size_t, but we depend on this +static_assert(sizeof(size_t) == sizeof(void *), "size_t and a pointer don't have the same size"); +static_assert(sizeof(size_t) == sizeof(qsizetype)); // implied by the definition +static_assert((std::is_same<qsizetype, qptrdiff>::value)); +static_assert(std::is_same_v<std::size_t, size_t>); + +// Check that our own typedefs are not broken. +static_assert(sizeof(qint8) == 1, "Internal error, qint8 is misdefined"); +static_assert(sizeof(qint16)== 2, "Internal error, qint16 is misdefined"); +static_assert(sizeof(qint32) == 4, "Internal error, qint32 is misdefined"); +static_assert(sizeof(qint64) == 8, "Internal error, qint64 is misdefined"); +#ifdef QT_SUPPORTS_INT128 +static_assert(sizeof(qint128) == 16, "Internal error, qint128 is misdefined"); +#endif + +#ifdef QT_SUPPORTS_INT128 +// Standard Library supports for 128-bit integers: +// Implementation | Version | Note +// ---------------------|---------|------ +// GNU libstdc++ | 11.1.0 | +// LLVM libc++ | 3.5 | May change if compiler has __is_integral() +// MS STL | none | + +# if defined(_LIBCPP_VERSION) || (defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE >= 11) +static_assert(std::numeric_limits<quint128>::max() == Q_UINT128_MAX); +# endif +#endif + +QT_END_NAMESPACE |