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 | |