1// Copyright 2016 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <assert.h>
6#include <inttypes.h>
7#include <limits.h>
8#include <signal.h>
9#include <stdint.h>
10#include <wchar.h>
11
12#include <unittest/unittest.h>
13
14// stdint.h defines the following types:
15// Fixed width types:
16// int8_t
17// int16_t
18// int32_t
19// int64_t
20// uint8_t
21// uint16_t
22// uint32_t
23// uint64_t
24
25// Minimum width types:
26// int_least8_t
27// int_least16_t
28// int_least32_t
29// int_least64_t
30// uint_least8_t
31// uint_least16_t
32// uint_least32_t
33// uint_least64_t
34
35// Fast minimum width types:
36// int_fast8_t
37// int_fast16_t
38// int_fast32_t
39// int_fast64_t
40// uint_fast8_t
41// uint_fast16_t
42// uint_fast32_t
43// uint_fast64_t
44
45// Pointer-sized types:
46// intptr_t
47// uintptr_t
48
49// Maximum-width types:
50// intmax_t
51// uintmax_t
52
53// stddef.h defines the following types:
54// ptrdiff_t
55// size_t
56// wchar_t
57
58// signal.h defines the following type:
59// sig_atomic_t
60
61// Test sizes.
62static_assert(CHAR_BIT == 8, "");
63
64static_assert(sizeof(int8_t) == 1, "");
65static_assert(sizeof(int16_t) == 2, "");
66static_assert(sizeof(int32_t) == 4, "");
67static_assert(sizeof(int64_t) == 8, "");
68static_assert(sizeof(uint8_t) == 1, "");
69static_assert(sizeof(uint16_t) == 2, "");
70static_assert(sizeof(uint32_t) == 4, "");
71static_assert(sizeof(uint64_t) == 8, "");
72
73static_assert(sizeof(int_least8_t) >= 1, "");
74static_assert(sizeof(int_least16_t) >= 2, "");
75static_assert(sizeof(int_least32_t) >= 4, "");
76static_assert(sizeof(int_least64_t) >= 8, "");
77static_assert(sizeof(uint_least8_t) >= 1, "");
78static_assert(sizeof(uint_least16_t) >= 2, "");
79static_assert(sizeof(uint_least32_t) >= 4, "");
80static_assert(sizeof(uint_least64_t) >= 8, "");
81
82static_assert(sizeof(int_fast8_t) >= 1, "");
83static_assert(sizeof(int_fast16_t) >= 2, "");
84static_assert(sizeof(int_fast32_t) >= 4, "");
85static_assert(sizeof(int_fast64_t) >= 8, "");
86static_assert(sizeof(uint_fast8_t) >= 1, "");
87static_assert(sizeof(uint_fast16_t) >= 2, "");
88static_assert(sizeof(uint_fast32_t) >= 4, "");
89static_assert(sizeof(uint_fast64_t) >= 8, "");
90
91static_assert(sizeof(intptr_t) == sizeof(void*), "");
92static_assert(sizeof(uintptr_t) == sizeof(void*), "");
93
94static_assert(sizeof(intmax_t) == 8, "");
95static_assert(sizeof(uintmax_t) == 8, "");
96
97static_assert(sizeof(ptrdiff_t) == sizeof(void*), "");
98static_assert(sizeof(size_t) == sizeof(void*), "");
99
100// No interesting guarantees can be made about the sizes of these:
101// wchar_t
102// sig_atomic_t
103
104#define IS_SIGNED(type) ((type)(-1) < (type)(0))
105
106// Check maximums.
107#define CHECK_MAX_TYPE(type, TYPE, max_t, MAX) \
108    ((max_t)TYPE##_MAX == (MAX >> (CHAR_BIT * (sizeof(max_t) - sizeof(type)))))
109
110#define CHECK_MAX_UNSIGNED(type, TYPE) CHECK_MAX_TYPE(type, TYPE, uintmax_t, UINTMAX_MAX)
111#define CHECK_MAX_SIGNED(type, TYPE) CHECK_MAX_TYPE(type, TYPE, intmax_t, INTMAX_MAX)
112
113#define CHECK_MAX(type, TYPE) static_assert(IS_SIGNED(type) ? CHECK_MAX_SIGNED(type, TYPE) : CHECK_MAX_UNSIGNED(type, TYPE), "");
114
115CHECK_MAX(int8_t, INT8);
116CHECK_MAX(int16_t, INT16);
117CHECK_MAX(int32_t, INT32);
118CHECK_MAX(int64_t, INT64);
119CHECK_MAX(uint8_t, UINT8);
120CHECK_MAX(uint16_t, UINT16);
121CHECK_MAX(uint32_t, UINT32);
122CHECK_MAX(uint64_t, UINT64);
123
124CHECK_MAX(int_least8_t, INT_LEAST8);
125CHECK_MAX(int_least16_t, INT_LEAST16);
126CHECK_MAX(int_least32_t, INT_LEAST32);
127CHECK_MAX(int_least64_t, INT_LEAST64);
128CHECK_MAX(uint_least8_t, UINT_LEAST8);
129CHECK_MAX(uint_least16_t, UINT_LEAST16);
130CHECK_MAX(uint_least32_t, UINT_LEAST32);
131CHECK_MAX(uint_least64_t, UINT_LEAST64);
132
133CHECK_MAX(int_fast8_t, INT_FAST8);
134CHECK_MAX(int_fast16_t, INT_FAST16);
135CHECK_MAX(int_fast32_t, INT_FAST32);
136CHECK_MAX(int_fast64_t, INT_FAST64);
137CHECK_MAX(uint_fast8_t, UINT_FAST8);
138CHECK_MAX(uint_fast16_t, UINT_FAST16);
139CHECK_MAX(uint_fast32_t, UINT_FAST32);
140CHECK_MAX(uint_fast64_t, UINT_FAST64);
141
142CHECK_MAX(intptr_t, INTPTR);
143CHECK_MAX(uintptr_t, UINTPTR);
144
145CHECK_MAX(intmax_t, INTMAX);
146CHECK_MAX(uintmax_t, UINTMAX);
147
148CHECK_MAX(ptrdiff_t, PTRDIFF);
149CHECK_MAX(size_t, SIZE);
150CHECK_MAX(wchar_t, WCHAR);
151
152CHECK_MAX(sig_atomic_t, SIG_ATOMIC);
153
154// Check minimums.
155#define CHECK_MIN_TYPE(type, TYPE)                                   \
156    ((intmax_t)TYPE##_MIN == (INTMAX_MIN >> (CHAR_BIT * (sizeof(intmax_t) - sizeof(type)))))
157
158#define CHECK_MIN(type, TYPE) static_assert(CHECK_MIN_TYPE(type, TYPE), "")
159
160CHECK_MIN(int8_t, INT8);
161CHECK_MIN(int16_t, INT16);
162CHECK_MIN(int32_t, INT32);
163CHECK_MIN(int64_t, INT64);
164
165CHECK_MIN(int_least8_t, INT_LEAST8);
166CHECK_MIN(int_least16_t, INT_LEAST16);
167CHECK_MIN(int_least32_t, INT_LEAST32);
168CHECK_MIN(int_least64_t, INT_LEAST64);
169
170CHECK_MIN(int_fast8_t, INT_FAST8);
171CHECK_MIN(int_fast16_t, INT_FAST16);
172CHECK_MIN(int_fast32_t, INT_FAST32);
173CHECK_MIN(int_fast64_t, INT_FAST64);
174
175CHECK_MIN(intptr_t, INTPTR);
176
177CHECK_MIN(intmax_t, INTMAX);
178
179CHECK_MIN(ptrdiff_t, PTRDIFF);
180static_assert(IS_SIGNED(wchar_t) ? CHECK_MIN_TYPE(wchar_t, WCHAR) : (WCHAR_MIN == 0), "");
181
182static_assert(IS_SIGNED(sig_atomic_t) ? CHECK_MIN_TYPE(sig_atomic_t, SIG_ATOMIC) : (SIG_ATOMIC_MIN == 0), "");
183
184// The INTN_C and UINTN_C macros expand into integer constants
185// "corresponding to the type int_leastN_t" and "uint_leastN_t"
186// respectively.
187
188static_assert(INT8_C(0) == 0, "");
189static_assert(INT8_C(-0x7f - 1) == -0x7f - 1, "");
190static_assert(INT8_C(0x7f) == 0x7f, "");
191
192static_assert(INT16_C(0) == 0, "");
193static_assert(INT16_C(-0x7fff - 1) == -0x7fff - 1, "");
194static_assert(INT16_C(0x7fff) == 0x7fff, "");
195
196static_assert(INT32_C(0) == 0, "");
197static_assert(INT32_C(-0x7fffffff - 1) == -0x7fffffff - 1, "");
198static_assert(INT32_C(0x7fffffff) == 0x7fffffff, "");
199
200static_assert(INT64_C(0) == 0, "");
201static_assert(INT64_C(-0x7fffffffffffffff - 1) == -0x7fffffffffffffff - 1, "");
202static_assert(INT64_C(0x7fffffffffffffff) == 0x7fffffffffffffff, "");
203
204
205static_assert(UINT8_C(0) == 0, "");
206static_assert(UINT8_C(0xff) == 0xff, "");
207
208static_assert(UINT16_C(0) == 0, "");
209static_assert(UINT16_C(0xffff) == 0xffff, "");
210
211static_assert(UINT32_C(0) == 0, "");
212static_assert(UINT32_C(0xffffffff) == 0xffffffff, "");
213
214static_assert(UINT64_C(0) == 0, "");
215static_assert(UINT64_C(0xffffffffffffffff) == 0xffffffffffffffff, "");
216
217
218// Unlike the above, the INTMAX_C and UINTMAX_C macros explicitly
219// produce values of type intmax_t and uintmax_t respectively, not
220// just compatible values.
221
222// In C, we settle for just comparing for equality.
223
224static_assert(INTMAX_C(0) == 0, "");
225static_assert(INTMAX_C(-0xffffffffffffffff - 1) == -0xffffffffffffffff - 1, "");
226static_assert(INTMAX_C(0x7fffffffffffffff) == 0x7fffffffffffffff, "");
227
228static_assert(UINTMAX_C(0) == 0, "");
229static_assert(UINTMAX_C(0xffffffffffffffff) == 0xffffffffffffffff, "");
230
231
232// Check PRI* and SCN* format strings.
233#define LAST(fmt) (fmt[strlen(fmt) - 1])
234
235// Signed format specifiers.
236#define CHECK_d(fmt) EXPECT_EQ(LAST(fmt), 'd', "incorrect format specifier")
237#define CHECK_i(fmt) EXPECT_EQ(LAST(fmt), 'i', "incorrect format specifier")
238
239// Unsigned format specifiers. Note that X is only used by printf, and
240// not also by scanf.
241#define CHECK_o(fmt) EXPECT_EQ(LAST(fmt), 'o', "incorrect format specifier")
242#define CHECK_u(fmt) EXPECT_EQ(LAST(fmt), 'u', "incorrect format specifier")
243#define CHECK_x(fmt) EXPECT_EQ(LAST(fmt), 'x', "incorrect format specifier")
244#define CHECK_X(fmt) EXPECT_EQ(LAST(fmt), 'X', "incorrect format specifier")
245
246#define CHECK_FORMAT_STRINGS(pri, scn, pcheck, scheck, type, max) do { \
247        pcheck(pri);                                                    \
248        scheck(scn);                                                    \
249        char buf[256] = {0};                                            \
250        ASSERT_GT(snprintf(buf, sizeof(buf), "%" pri, (type)max), 1, "");  \
251        type n = (type)0;                                               \
252        ASSERT_EQ(sscanf(buf, "%" scn, &n), 1, "");                        \
253        ASSERT_EQ(n, max, "");                                          \
254    } while (0)
255
256#define CHECK_SIGNED_FORMATS(size, type, max) do {                      \
257        CHECK_FORMAT_STRINGS(PRId ## size, SCNd ## size, CHECK_d, CHECK_d, type, max); \
258        CHECK_FORMAT_STRINGS(PRIi ## size, SCNi ## size, CHECK_i, CHECK_i, type, max); \
259    } while (0)
260
261// Since X is not used by scanf (only x), the last line has PRIX but
262// SCNx (upper and lower case).
263#define CHECK_UNSIGNED_FORMATS(size, type, max) do {                    \
264        CHECK_FORMAT_STRINGS(PRIo ## size, SCNo ## size, CHECK_o, CHECK_o, type, max); \
265        CHECK_FORMAT_STRINGS(PRIu ## size, SCNu ## size, CHECK_u, CHECK_u, type, max); \
266        CHECK_FORMAT_STRINGS(PRIx ## size, SCNx ## size, CHECK_x, CHECK_x, type, max); \
267        CHECK_FORMAT_STRINGS(PRIX ## size, SCNx ## size, CHECK_X, CHECK_x, type, max); \
268    } while (0)
269
270#define CHECK_FORMATS(size, type, max) do {             \
271        if (IS_SIGNED(type)) {                          \
272            CHECK_SIGNED_FORMATS(size, type, max);      \
273        } else {                                        \
274            CHECK_UNSIGNED_FORMATS(size, type, max);    \
275        }                                               \
276    } while (0)
277
278static bool check_format_specifiers(void) {
279    BEGIN_TEST;
280
281    CHECK_FORMATS(8, int8_t, INT8_MAX);
282    CHECK_FORMATS(16, int16_t, INT16_MAX);
283    CHECK_FORMATS(32, int32_t, INT32_MAX);
284    CHECK_FORMATS(64, int64_t, INT64_MAX);
285    CHECK_FORMATS(8, uint8_t, UINT8_MAX);
286    CHECK_FORMATS(16, uint16_t, UINT16_MAX);
287    CHECK_FORMATS(32, uint32_t, UINT32_MAX);
288    CHECK_FORMATS(64, uint64_t, UINT64_MAX);
289
290    CHECK_FORMATS(FAST8, int_fast8_t, INT_FAST8_MAX);
291    CHECK_FORMATS(FAST16, int_fast16_t, INT_FAST16_MAX);
292    CHECK_FORMATS(FAST32, int_fast32_t, INT_FAST32_MAX);
293    CHECK_FORMATS(FAST64, int_fast64_t, INT_FAST64_MAX);
294    CHECK_FORMATS(FAST8, uint_fast8_t, UINT_FAST8_MAX);
295    CHECK_FORMATS(FAST16, uint_fast16_t, UINT_FAST16_MAX);
296    CHECK_FORMATS(FAST32, uint_fast32_t, UINT_FAST32_MAX);
297    CHECK_FORMATS(FAST64, uint_fast64_t, UINT_FAST64_MAX);
298
299    CHECK_FORMATS(LEAST8, int_least8_t, INT_LEAST8_MAX);
300    CHECK_FORMATS(LEAST16, int_least16_t, INT_LEAST16_MAX);
301    CHECK_FORMATS(LEAST32, int_least32_t, INT_LEAST32_MAX);
302    CHECK_FORMATS(LEAST64, int_least64_t, INT_LEAST64_MAX);
303    CHECK_FORMATS(LEAST8, uint_least8_t, UINT_LEAST8_MAX);
304    CHECK_FORMATS(LEAST16, uint_least16_t, UINT_LEAST16_MAX);
305    CHECK_FORMATS(LEAST32, uint_least32_t, UINT_LEAST32_MAX);
306    CHECK_FORMATS(LEAST64, uint_least64_t, UINT_LEAST64_MAX);
307
308    CHECK_FORMATS(PTR, intptr_t, INTPTR_MAX);
309    CHECK_FORMATS(PTR, uintptr_t, UINTPTR_MAX);
310
311    // Note that these are definined in addition to %j
312    CHECK_FORMATS(MAX, intmax_t, INTMAX_MAX);
313    CHECK_FORMATS(MAX, uintmax_t, UINTMAX_MAX);
314
315    // ptrdiff_t is simply %t.
316    // size_t is simply %z.
317    // wchar_t is simply %sl.
318
319    // No particular format specifier or macro is defined for sig_atomic_t.
320
321    END_TEST;
322}
323
324BEGIN_TEST_CASE(c_format_specifiers)
325RUN_TEST(check_format_specifiers)
326END_TEST_CASE(c_format_specifiers)
327