// 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 #ifndef QTYPES_H #define QTYPES_H #include #include #include #ifdef __cplusplus # include # include # if defined(__STDCPP_FLOAT16_T__) && __has_include() // P1467 implementation - https://wg21.link/p1467 # include # endif // defined(__STDCPP_FLOAT16_T__) && __has_include() #else # include #endif #if 0 #pragma qt_class(QtTypes) #pragma qt_class(QIntegerForSize) #pragma qt_sync_stop_processing #endif /* Useful type definitions for Qt */ typedef unsigned char uchar; typedef unsigned short ushort; typedef unsigned int uint; typedef unsigned long ulong; QT_BEGIN_NAMESPACE /* Size-dependent types (architecture-dependent byte order) Make sure to update QMetaType when changing these typedefs */ typedef signed char qint8; /* 8 bit signed */ typedef unsigned char quint8; /* 8 bit unsigned */ typedef short qint16; /* 16 bit signed */ typedef unsigned short quint16; /* 16 bit unsigned */ typedef int qint32; /* 32 bit signed */ typedef unsigned int quint32; /* 32 bit unsigned */ // Unlike LL / ULL in C++, for historical reasons, we force the // result to be of the requested type. #ifdef __cplusplus # define Q_INT64_C(c) static_cast(c ## LL) /* signed 64 bit constant */ # define Q_UINT64_C(c) static_cast(c ## ULL) /* unsigned 64 bit constant */ #else # define Q_INT64_C(c) ((long long)(c ## LL)) /* signed 64 bit constant */ # define Q_UINT64_C(c) ((unsigned long long)(c ## ULL)) /* unsigned 64 bit constant */ #endif typedef long long qint64; /* 64 bit signed */ typedef unsigned long long quint64; /* 64 bit unsigned */ typedef qint64 qlonglong; typedef quint64 qulonglong; #if defined(__SIZEOF_INT128__) && !defined(QT_NO_INT128) # define QT_SUPPORTS_INT128 __SIZEOF_INT128__ #else # undef QT_SUPPORTS_INT128 #endif #if defined(QT_SUPPORTS_INT128) __extension__ typedef __int128_t qint128; __extension__ typedef __uint128_t quint128; // limits: # ifdef __cplusplus /* need to avoid c-style-casts in C++ mode */ # define QT_C_STYLE_CAST(type, x) static_cast(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) # ifdef __cplusplus namespace QtPrivate::NumberLiterals { namespace detail { template constexpr quint128 construct() { return accu; } template constexpr quint128 construct() { if constexpr (C != '\'') { // ignore digit separators const int digitValue = '0' <= C && C <= '9' ? C - '0' : 'a' <= C && C <= 'z' ? C - 'a' + 10 : 'A' <= C && C <= 'Z' ? C - 'A' + 10 : /* else */ -1 ; static_assert(digitValue >= 0 && digitValue < base, "Invalid character"); // accu * base + digitValue <= MAX, but without overflow: static_assert(accu <= (Q_UINT128_MAX - digitValue) / base, "Overflow occurred"); return construct(); } else { return construct(); } } template constexpr quint128 parse0xb() { constexpr quint128 accu = 0; if constexpr (C == 'x' || C == 'X') return construct(); // base 16, skip 'x' else if constexpr (C == 'b' || C == 'B') return construct(); // base 2, skip 'b' else return construct(); // base 8, include C } template constexpr quint128 parse0() { if constexpr (sizeof...(Cs) == 0) // this was just a literal 0 return 0; else return parse0xb(); } template constexpr quint128 parse() { if constexpr (C == '0') return parse0(); // base 2, 8, or 16 (or just a literal 0), skip '0' else return construct<0, 10, C, Cs...>(); // initial accu 0, base 10, include C } } // namespace detail template constexpr quint128 operator""_quint128() noexcept { return QtPrivate::NumberLiterals::detail::parse(); } template constexpr qint128 operator""_qint128() noexcept { return qint128(QtPrivate::NumberLiterals::detail::parse()); } #ifndef Q_UINT128_C // allow qcompilerdetection.h/user override # define Q_UINT128_C(c) ([]{ using namespace QtPrivate::NumberLiterals; return c ## _quint128; }()) #endif #ifndef Q_INT128_C // allow qcompilerdetection.h/user override # define Q_INT128_C(c) ([]{ using namespace QtPrivate::NumberLiterals; return c ## _qint128; }()) #endif } // namespace QtPrivate::NumberLiterals # endif // __cplusplus #endif // QT_SUPPORTS_INT128 #ifndef __cplusplus // In C++ mode, we define below using QIntegerForSize template static_assert(sizeof(ptrdiff_t) == sizeof(size_t), "Weird ptrdiff_t and size_t definitions"); typedef ptrdiff_t qptrdiff; typedef ptrdiff_t qsizetype; typedef ptrdiff_t qintptr; typedef size_t quintptr; #define PRIdQPTRDIFF "td" #define PRIiQPTRDIFF "ti" #define PRIdQSIZETYPE "td" #define PRIiQSIZETYPE "ti" #define PRIdQINTPTR "td" #define PRIiQINTPTR "ti" #define PRIuQUINTPTR "zu" #define PRIoQUINTPTR "zo" #define PRIxQUINTPTR "zx" #define PRIXQUINTPTR "zX" #endif #if defined(QT_COORD_TYPE) typedef QT_COORD_TYPE qreal; #else typedef double qreal; #endif #if defined(__cplusplus) /* quintptr are qptrdiff is guaranteed to be the same size as a pointer, i.e. sizeof(void *) == sizeof(quintptr) && sizeof(void *) == sizeof(qptrdiff) While size_t and qsizetype are not guaranteed to be the same size as a pointer, they usually are and we do check for that in qtypes.cpp, just to be sure. */ template struct QIntegerForSize; template <> struct QIntegerForSize<1> { typedef quint8 Unsigned; typedef qint8 Signed; }; template <> struct QIntegerForSize<2> { typedef quint16 Unsigned; typedef qint16 Signed; }; template <> struct QIntegerForSize<4> { typedef quint32 Unsigned; typedef qint32 Signed; }; template <> struct QIntegerForSize<8> { typedef quint64 Unsigned; typedef qint64 Signed; }; #if defined(QT_SUPPORTS_INT128) template <> struct QIntegerForSize<16> { typedef quint128 Unsigned; typedef qint128 Signed; }; #endif template struct QIntegerForSizeof: QIntegerForSize { }; typedef QIntegerForSize::Signed qregisterint; typedef QIntegerForSize::Unsigned qregisteruint; typedef QIntegerForSizeof::Unsigned quintptr; typedef QIntegerForSizeof::Signed qptrdiff; typedef qptrdiff qintptr; using qsizetype = QIntegerForSizeof::Signed; // These custom definitions are necessary as we're not defining our // datatypes in terms of the language ones, but in terms of integer // types that have the sime size. For instance, on a 32-bit platform, // qptrdiff is int, while ptrdiff_t may be aliased to long; therefore // using %td to print a qptrdiff would be wrong (and raise -Wformat // warnings), although both int and long have same bit size on that // platform. // // We know that sizeof(size_t) == sizeof(void *) == sizeof(qptrdiff). #if SIZE_MAX == 0xffffffffULL #define PRIuQUINTPTR "u" #define PRIoQUINTPTR "o" #define PRIxQUINTPTR "x" #define PRIXQUINTPTR "X" #define PRIdQPTRDIFF "d" #define PRIiQPTRDIFF "i" #define PRIdQINTPTR "d" #define PRIiQINTPTR "i" #define PRIdQSIZETYPE "d" #define PRIiQSIZETYPE "i" #elif SIZE_MAX == 0xffffffffffffffffULL #define PRIuQUINTPTR "llu" #define PRIoQUINTPTR "llo" #define PRIxQUINTPTR "llx" #define PRIXQUINTPTR "llX" #define PRIdQPTRDIFF "lld" #define PRIiQPTRDIFF "lli" #define PRIdQINTPTR "lld" #define PRIiQINTPTR "lli" #define PRIdQSIZETYPE "lld" #define PRIiQSIZETYPE "lli" #else #error Unsupported platform (unknown value for SIZE_MAX) #endif // Define a native float16 type namespace QtPrivate { #if defined(__STDCPP_FLOAT16_T__) # define QFLOAT16_IS_NATIVE 1 using NativeFloat16Type = std::float16_t; #elif defined(Q_CC_CLANG) && defined(__FLT16_MAX__) && 0 // disabled due to https://github.com/llvm/llvm-project/issues/56963 # define QFLOAT16_IS_NATIVE 1 using NativeFloat16Type = decltype(__FLT16_MAX__); #elif defined(Q_CC_GNU_ONLY) && defined(__FLT16_MAX__) # define QFLOAT16_IS_NATIVE 1 # ifdef __ARM_FP16_FORMAT_IEEE using NativeFloat16Type = __fp16; # else using NativeFloat16Type = _Float16; # endif #else # define QFLOAT16_IS_NATIVE 0 using NativeFloat16Type = void; #endif } // QtPrivate #endif // __cplusplus QT_END_NAMESPACE #endif // QTYPES_H