| 1 | // Copyright (C) 2022 The Qt Company Ltd. |
| 2 | // Copyright (C) 2022 Intel Corporation. |
| 3 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
| 4 | |
| 5 | #ifndef QTYPES_H |
| 6 | #define QTYPES_H |
| 7 | |
| 8 | #include <QtCore/qprocessordetection.h> |
| 9 | #include <QtCore/qsystemdetection.h> |
| 10 | #include <QtCore/qtconfigmacros.h> |
| 11 | #include <QtCore/qassert.h> |
| 12 | |
| 13 | #ifdef __cplusplus |
| 14 | # include <cstddef> |
| 15 | # if defined(_HAS_STD_BYTE) && _HAS_STD_BYTE == 0 |
| 16 | # error "Qt requires std::byte, but _HAS_STD_BYTE has been set to 0" |
| 17 | # endif |
| 18 | # include <cstdint> |
| 19 | # if defined(__STDCPP_FLOAT16_T__) && __has_include(<stdfloat>) |
| 20 | // P1467 implementation - https://wg21.link/p1467 |
| 21 | # include <stdfloat> |
| 22 | # endif // defined(__STDCPP_FLOAT16_T__) && __has_include(<stdfloat>) |
| 23 | # include <type_traits> |
| 24 | #else |
| 25 | # include <assert.h> |
| 26 | #endif |
| 27 | |
| 28 | #if 0 |
| 29 | #pragma qt_class(QtTypes) |
| 30 | #pragma qt_class(QIntegerForSize) |
| 31 | #pragma qt_sync_stop_processing |
| 32 | #endif |
| 33 | |
| 34 | /* |
| 35 | Useful type definitions for Qt |
| 36 | */ |
| 37 | typedef unsigned char uchar; |
| 38 | typedef unsigned short ushort; |
| 39 | typedef unsigned int uint; |
| 40 | typedef unsigned long ulong; |
| 41 | |
| 42 | QT_BEGIN_NAMESPACE |
| 43 | |
| 44 | /* |
| 45 | Size-dependent types (architecture-dependent byte order) |
| 46 | |
| 47 | Make sure to update QMetaType when changing these typedefs |
| 48 | */ |
| 49 | |
| 50 | typedef signed char qint8; /* 8 bit signed */ |
| 51 | typedef unsigned char quint8; /* 8 bit unsigned */ |
| 52 | typedef short qint16; /* 16 bit signed */ |
| 53 | typedef unsigned short quint16; /* 16 bit unsigned */ |
| 54 | typedef int qint32; /* 32 bit signed */ |
| 55 | typedef unsigned int quint32; /* 32 bit unsigned */ |
| 56 | // Unlike LL / ULL in C++, for historical reasons, we force the |
| 57 | // result to be of the requested type. |
| 58 | #ifdef __cplusplus |
| 59 | # define Q_INT64_C(c) static_cast<long long>(c ## LL) /* signed 64 bit constant */ |
| 60 | # define Q_UINT64_C(c) static_cast<unsigned long long>(c ## ULL) /* unsigned 64 bit constant */ |
| 61 | #else |
| 62 | # define Q_INT64_C(c) ((long long)(c ## LL)) /* signed 64 bit constant */ |
| 63 | # define Q_UINT64_C(c) ((unsigned long long)(c ## ULL)) /* unsigned 64 bit constant */ |
| 64 | #endif |
| 65 | typedef long long qint64; /* 64 bit signed */ |
| 66 | typedef unsigned long long quint64; /* 64 bit unsigned */ |
| 67 | |
| 68 | typedef qint64 qlonglong; |
| 69 | typedef quint64 qulonglong; |
| 70 | |
| 71 | #ifdef Q_QDOC // QDoc always needs to see the typedefs |
| 72 | # define QT_SUPPORTS_INT128 16 |
| 73 | #elif defined(QT_COMPILER_SUPPORTS_INT128) && !defined(QT_NO_INT128) |
| 74 | # define QT_SUPPORTS_INT128 QT_COMPILER_SUPPORTS_INT128 |
| 75 | # if defined(__GLIBCXX__) && defined(__STRICT_ANSI__) // -ansi/-std=c++NN instead of gnu++NN |
| 76 | # undef QT_SUPPORTS_INT128 // breaks <type_traits> on libstdc++ |
| 77 | # endif |
| 78 | # if defined(__clang__) && defined(_MSVC_STL_VERSION) // Clang with MSVC's STL |
| 79 | # undef QT_SUPPORTS_INT128 // MSVC's STL doesn't support int128 |
| 80 | # endif |
| 81 | #else |
| 82 | # undef QT_SUPPORTS_INT128 |
| 83 | #endif |
| 84 | |
| 85 | #if defined(QT_SUPPORTS_INT128) |
| 86 | __extension__ typedef __int128_t qint128; |
| 87 | __extension__ typedef __uint128_t quint128; |
| 88 | |
| 89 | #ifdef __cplusplus |
| 90 | static_assert(std::is_signed_v<qint128>, |
| 91 | "Qt requires <type_traits> and <limits> to work for q(u)int128." ); |
| 92 | #endif |
| 93 | |
| 94 | // limits: |
| 95 | # ifdef __cplusplus /* need to avoid c-style-casts in C++ mode */ |
| 96 | # define QT_C_STYLE_CAST(type, x) static_cast<type>(x) |
| 97 | # else /* but C doesn't have constructor-style casts */ |
| 98 | # define QT_C_STYLE_CAST(type, x) ((type)(x)) |
| 99 | # endif |
| 100 | # ifndef Q_UINT128_MAX /* allow qcompilerdetection.h/user override */ |
| 101 | # define Q_UINT128_MAX QT_C_STYLE_CAST(quint128, -1) |
| 102 | # endif |
| 103 | # define Q_INT128_MAX QT_C_STYLE_CAST(qint128, Q_UINT128_MAX / 2) |
| 104 | # define Q_INT128_MIN (-Q_INT128_MAX - 1) |
| 105 | |
| 106 | # ifdef __cplusplus |
| 107 | namespace QtPrivate::NumberLiterals { |
| 108 | namespace detail { |
| 109 | template <quint128 accu, int base> |
| 110 | constexpr quint128 construct() { return accu; } |
| 111 | |
| 112 | template <quint128 accu, int base, char C, char...Cs> |
| 113 | constexpr quint128 construct() |
| 114 | { |
| 115 | if constexpr (C != '\'') { // ignore digit separators |
| 116 | const int digitValue = '0' <= C && C <= '9' ? C - '0' : |
| 117 | 'a' <= C && C <= 'z' ? C - 'a' + 10 : |
| 118 | 'A' <= C && C <= 'Z' ? C - 'A' + 10 : |
| 119 | /* else */ -1 ; |
| 120 | static_assert(digitValue >= 0 && digitValue < base, |
| 121 | "Invalid character" ); |
| 122 | // accu * base + digitValue <= MAX, but without overflow: |
| 123 | static_assert(accu <= (Q_UINT128_MAX - digitValue) / base, |
| 124 | "Overflow occurred" ); |
| 125 | return construct<accu * base + digitValue, base, Cs...>(); |
| 126 | } else { |
| 127 | return construct<accu, base, Cs...>(); |
| 128 | } |
| 129 | } |
| 130 | |
| 131 | template <char C, char...Cs> |
| 132 | constexpr quint128 parse0xb() |
| 133 | { |
| 134 | constexpr quint128 accu = 0; |
| 135 | if constexpr (C == 'x' || C == 'X') |
| 136 | return construct<accu, 16, Cs...>(); // base 16, skip 'x' |
| 137 | else if constexpr (C == 'b' || C == 'B') |
| 138 | return construct<accu, 2, Cs...>(); // base 2, skip 'b' |
| 139 | else |
| 140 | return construct<accu, 8, C, Cs...>(); // base 8, include C |
| 141 | } |
| 142 | |
| 143 | template <char...Cs> |
| 144 | constexpr quint128 parse0() |
| 145 | { |
| 146 | if constexpr (sizeof...(Cs) == 0) // this was just a literal 0 |
| 147 | return 0; |
| 148 | else |
| 149 | return parse0xb<Cs...>(); |
| 150 | } |
| 151 | |
| 152 | template <char C, char...Cs> |
| 153 | constexpr quint128 parse() |
| 154 | { |
| 155 | if constexpr (C == '0') |
| 156 | return parse0<Cs...>(); // base 2, 8, or 16 (or just a literal 0), skip '0' |
| 157 | else |
| 158 | return construct<0, 10, C, Cs...>(); // initial accu 0, base 10, include C |
| 159 | } |
| 160 | } // namespace detail |
| 161 | template <char...Cs> |
| 162 | constexpr quint128 operator""_quint128 () noexcept |
| 163 | { return QtPrivate::NumberLiterals::detail::parse<Cs...>(); } |
| 164 | template <char...Cs> |
| 165 | constexpr qint128 operator""_qint128 () noexcept |
| 166 | { return qint128(QtPrivate::NumberLiterals::detail::parse<Cs...>()); } |
| 167 | |
| 168 | #ifndef Q_UINT128_C // allow qcompilerdetection.h/user override |
| 169 | # define Q_UINT128_C(c) ([]{ using namespace QtPrivate::NumberLiterals; return c ## _quint128; }()) |
| 170 | #endif |
| 171 | #ifndef Q_INT128_C // allow qcompilerdetection.h/user override |
| 172 | # define Q_INT128_C(c) ([]{ using namespace QtPrivate::NumberLiterals; return c ## _qint128; }()) |
| 173 | #endif |
| 174 | |
| 175 | } // namespace QtPrivate::NumberLiterals |
| 176 | # endif // __cplusplus |
| 177 | #endif // QT_SUPPORTS_INT128 |
| 178 | |
| 179 | #ifndef __cplusplus |
| 180 | // In C++ mode, we define below using QIntegerForSize template |
| 181 | static_assert(sizeof(ptrdiff_t) == sizeof(size_t), "Weird ptrdiff_t and size_t definitions" ); |
| 182 | typedef ptrdiff_t qptrdiff; |
| 183 | typedef ptrdiff_t qsizetype; |
| 184 | typedef ptrdiff_t qintptr; |
| 185 | typedef size_t quintptr; |
| 186 | |
| 187 | #define PRIdQPTRDIFF "td" |
| 188 | #define PRIiQPTRDIFF "ti" |
| 189 | |
| 190 | #define PRIdQSIZETYPE "td" |
| 191 | #define PRIiQSIZETYPE "ti" |
| 192 | |
| 193 | #define PRIdQINTPTR "td" |
| 194 | #define PRIiQINTPTR "ti" |
| 195 | |
| 196 | #define PRIuQUINTPTR "zu" |
| 197 | #define PRIoQUINTPTR "zo" |
| 198 | #define PRIxQUINTPTR "zx" |
| 199 | #define PRIXQUINTPTR "zX" |
| 200 | #endif |
| 201 | |
| 202 | #if defined(QT_COORD_TYPE) |
| 203 | typedef QT_COORD_TYPE qreal; |
| 204 | #else |
| 205 | typedef double qreal; |
| 206 | #endif |
| 207 | |
| 208 | #if defined(__cplusplus) |
| 209 | /* |
| 210 | quintptr are qptrdiff is guaranteed to be the same size as a pointer, i.e. |
| 211 | |
| 212 | sizeof(void *) == sizeof(quintptr) |
| 213 | && sizeof(void *) == sizeof(qptrdiff) |
| 214 | |
| 215 | While size_t and qsizetype are not guaranteed to be the same size as a pointer, |
| 216 | they usually are and we do check for that in qtypes.cpp, just to be sure. |
| 217 | */ |
| 218 | template <int> struct QIntegerForSize; |
| 219 | template <> struct QIntegerForSize<1> { typedef quint8 Unsigned; typedef qint8 Signed; }; |
| 220 | template <> struct QIntegerForSize<2> { typedef quint16 Unsigned; typedef qint16 Signed; }; |
| 221 | template <> struct QIntegerForSize<4> { typedef quint32 Unsigned; typedef qint32 Signed; }; |
| 222 | template <> struct QIntegerForSize<8> { typedef quint64 Unsigned; typedef qint64 Signed; }; |
| 223 | #if defined(QT_SUPPORTS_INT128) |
| 224 | template <> struct QIntegerForSize<16> { typedef quint128 Unsigned; typedef qint128 Signed; }; |
| 225 | #endif |
| 226 | template <class T> struct QIntegerForSizeof: QIntegerForSize<sizeof(T)> { }; |
| 227 | typedef QIntegerForSize<Q_PROCESSOR_WORDSIZE>::Signed qregisterint; |
| 228 | typedef QIntegerForSize<Q_PROCESSOR_WORDSIZE>::Unsigned qregisteruint; |
| 229 | typedef QIntegerForSizeof<void *>::Unsigned quintptr; |
| 230 | typedef QIntegerForSizeof<void *>::Signed qptrdiff; |
| 231 | typedef qptrdiff qintptr; |
| 232 | using qsizetype = QIntegerForSizeof<std::size_t>::Signed; |
| 233 | |
| 234 | // These custom definitions are necessary as we're not defining our |
| 235 | // datatypes in terms of the language ones, but in terms of integer |
| 236 | // types that have the sime size. For instance, on a 32-bit platform, |
| 237 | // qptrdiff is int, while ptrdiff_t may be aliased to long; therefore |
| 238 | // using %td to print a qptrdiff would be wrong (and raise -Wformat |
| 239 | // warnings), although both int and long have same bit size on that |
| 240 | // platform. |
| 241 | // |
| 242 | // We know that sizeof(size_t) == sizeof(void *) == sizeof(qptrdiff). |
| 243 | #if SIZE_MAX == 0xffffffffULL |
| 244 | #define PRIuQUINTPTR "u" |
| 245 | #define PRIoQUINTPTR "o" |
| 246 | #define PRIxQUINTPTR "x" |
| 247 | #define PRIXQUINTPTR "X" |
| 248 | |
| 249 | #define PRIdQPTRDIFF "d" |
| 250 | #define PRIiQPTRDIFF "i" |
| 251 | |
| 252 | #define PRIdQINTPTR "d" |
| 253 | #define PRIiQINTPTR "i" |
| 254 | |
| 255 | #define PRIdQSIZETYPE "d" |
| 256 | #define PRIiQSIZETYPE "i" |
| 257 | #elif SIZE_MAX == 0xffffffffffffffffULL |
| 258 | #define PRIuQUINTPTR "llu" |
| 259 | #define PRIoQUINTPTR "llo" |
| 260 | #define PRIxQUINTPTR "llx" |
| 261 | #define PRIXQUINTPTR "llX" |
| 262 | |
| 263 | #define PRIdQPTRDIFF "lld" |
| 264 | #define PRIiQPTRDIFF "lli" |
| 265 | |
| 266 | #define PRIdQINTPTR "lld" |
| 267 | #define PRIiQINTPTR "lli" |
| 268 | |
| 269 | #define PRIdQSIZETYPE "lld" |
| 270 | #define PRIiQSIZETYPE "lli" |
| 271 | #else |
| 272 | #error Unsupported platform (unknown value for SIZE_MAX) |
| 273 | #endif |
| 274 | |
| 275 | // Define a native float16 type |
| 276 | namespace QtPrivate { |
| 277 | #if defined(__STDCPP_FLOAT16_T__) |
| 278 | # define QFLOAT16_IS_NATIVE 1 |
| 279 | using NativeFloat16Type = std::float16_t; |
| 280 | #elif defined(Q_CC_CLANG) && defined(__FLT16_MAX__) && 0 |
| 281 | // disabled due to https://github.com/llvm/llvm-project/issues/56963 |
| 282 | # define QFLOAT16_IS_NATIVE 1 |
| 283 | using NativeFloat16Type = decltype(__FLT16_MAX__); |
| 284 | #elif defined(Q_CC_GNU_ONLY) && defined(__FLT16_MAX__) && defined(__ARM_FP16_FORMAT_IEEE) |
| 285 | # define QFLOAT16_IS_NATIVE 1 |
| 286 | using NativeFloat16Type = __fp16; |
| 287 | #elif defined(Q_CC_GNU_ONLY) && defined(__FLT16_MAX__) && defined(__SSE2__) |
| 288 | # define QFLOAT16_IS_NATIVE 1 |
| 289 | using NativeFloat16Type = _Float16; |
| 290 | #else |
| 291 | # define QFLOAT16_IS_NATIVE 0 |
| 292 | using NativeFloat16Type = void; |
| 293 | #endif |
| 294 | } // QtPrivate |
| 295 | |
| 296 | #endif // __cplusplus |
| 297 | |
| 298 | QT_END_NAMESPACE |
| 299 | |
| 300 | #endif // QTYPES_H |
| 301 | |