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.
62 static_assert(CHAR_BIT == 8, "");
63
64 static_assert(sizeof(int8_t) == 1, "");
65 static_assert(sizeof(int16_t) == 2, "");
66 static_assert(sizeof(int32_t) == 4, "");
67 static_assert(sizeof(int64_t) == 8, "");
68 static_assert(sizeof(uint8_t) == 1, "");
69 static_assert(sizeof(uint16_t) == 2, "");
70 static_assert(sizeof(uint32_t) == 4, "");
71 static_assert(sizeof(uint64_t) == 8, "");
72
73 static_assert(sizeof(int_least8_t) >= 1, "");
74 static_assert(sizeof(int_least16_t) >= 2, "");
75 static_assert(sizeof(int_least32_t) >= 4, "");
76 static_assert(sizeof(int_least64_t) >= 8, "");
77 static_assert(sizeof(uint_least8_t) >= 1, "");
78 static_assert(sizeof(uint_least16_t) >= 2, "");
79 static_assert(sizeof(uint_least32_t) >= 4, "");
80 static_assert(sizeof(uint_least64_t) >= 8, "");
81
82 static_assert(sizeof(int_fast8_t) >= 1, "");
83 static_assert(sizeof(int_fast16_t) >= 2, "");
84 static_assert(sizeof(int_fast32_t) >= 4, "");
85 static_assert(sizeof(int_fast64_t) >= 8, "");
86 static_assert(sizeof(uint_fast8_t) >= 1, "");
87 static_assert(sizeof(uint_fast16_t) >= 2, "");
88 static_assert(sizeof(uint_fast32_t) >= 4, "");
89 static_assert(sizeof(uint_fast64_t) >= 8, "");
90
91 static_assert(sizeof(intptr_t) == sizeof(void*), "");
92 static_assert(sizeof(uintptr_t) == sizeof(void*), "");
93
94 static_assert(sizeof(intmax_t) == 8, "");
95 static_assert(sizeof(uintmax_t) == 8, "");
96
97 static_assert(sizeof(ptrdiff_t) == sizeof(void*), "");
98 static_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
115 CHECK_MAX(int8_t, INT8);
116 CHECK_MAX(int16_t, INT16);
117 CHECK_MAX(int32_t, INT32);
118 CHECK_MAX(int64_t, INT64);
119 CHECK_MAX(uint8_t, UINT8);
120 CHECK_MAX(uint16_t, UINT16);
121 CHECK_MAX(uint32_t, UINT32);
122 CHECK_MAX(uint64_t, UINT64);
123
124 CHECK_MAX(int_least8_t, INT_LEAST8);
125 CHECK_MAX(int_least16_t, INT_LEAST16);
126 CHECK_MAX(int_least32_t, INT_LEAST32);
127 CHECK_MAX(int_least64_t, INT_LEAST64);
128 CHECK_MAX(uint_least8_t, UINT_LEAST8);
129 CHECK_MAX(uint_least16_t, UINT_LEAST16);
130 CHECK_MAX(uint_least32_t, UINT_LEAST32);
131 CHECK_MAX(uint_least64_t, UINT_LEAST64);
132
133 CHECK_MAX(int_fast8_t, INT_FAST8);
134 CHECK_MAX(int_fast16_t, INT_FAST16);
135 CHECK_MAX(int_fast32_t, INT_FAST32);
136 CHECK_MAX(int_fast64_t, INT_FAST64);
137 CHECK_MAX(uint_fast8_t, UINT_FAST8);
138 CHECK_MAX(uint_fast16_t, UINT_FAST16);
139 CHECK_MAX(uint_fast32_t, UINT_FAST32);
140 CHECK_MAX(uint_fast64_t, UINT_FAST64);
141
142 CHECK_MAX(intptr_t, INTPTR);
143 CHECK_MAX(uintptr_t, UINTPTR);
144
145 CHECK_MAX(intmax_t, INTMAX);
146 CHECK_MAX(uintmax_t, UINTMAX);
147
148 CHECK_MAX(ptrdiff_t, PTRDIFF);
149 CHECK_MAX(size_t, SIZE);
150 CHECK_MAX(wchar_t, WCHAR);
151
152 CHECK_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
160 CHECK_MIN(int8_t, INT8);
161 CHECK_MIN(int16_t, INT16);
162 CHECK_MIN(int32_t, INT32);
163 CHECK_MIN(int64_t, INT64);
164
165 CHECK_MIN(int_least8_t, INT_LEAST8);
166 CHECK_MIN(int_least16_t, INT_LEAST16);
167 CHECK_MIN(int_least32_t, INT_LEAST32);
168 CHECK_MIN(int_least64_t, INT_LEAST64);
169
170 CHECK_MIN(int_fast8_t, INT_FAST8);
171 CHECK_MIN(int_fast16_t, INT_FAST16);
172 CHECK_MIN(int_fast32_t, INT_FAST32);
173 CHECK_MIN(int_fast64_t, INT_FAST64);
174
175 CHECK_MIN(intptr_t, INTPTR);
176
177 CHECK_MIN(intmax_t, INTMAX);
178
179 CHECK_MIN(ptrdiff_t, PTRDIFF);
180 static_assert(IS_SIGNED(wchar_t) ? CHECK_MIN_TYPE(wchar_t, WCHAR) : (WCHAR_MIN == 0), "");
181
182 static_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
188 static_assert(INT8_C(0) == 0, "");
189 static_assert(INT8_C(-0x7f - 1) == -0x7f - 1, "");
190 static_assert(INT8_C(0x7f) == 0x7f, "");
191
192 static_assert(INT16_C(0) == 0, "");
193 static_assert(INT16_C(-0x7fff - 1) == -0x7fff - 1, "");
194 static_assert(INT16_C(0x7fff) == 0x7fff, "");
195
196 static_assert(INT32_C(0) == 0, "");
197 static_assert(INT32_C(-0x7fffffff - 1) == -0x7fffffff - 1, "");
198 static_assert(INT32_C(0x7fffffff) == 0x7fffffff, "");
199
200 static_assert(INT64_C(0) == 0, "");
201 static_assert(INT64_C(-0x7fffffffffffffff - 1) == -0x7fffffffffffffff - 1, "");
202 static_assert(INT64_C(0x7fffffffffffffff) == 0x7fffffffffffffff, "");
203
204
205 static_assert(UINT8_C(0) == 0, "");
206 static_assert(UINT8_C(0xff) == 0xff, "");
207
208 static_assert(UINT16_C(0) == 0, "");
209 static_assert(UINT16_C(0xffff) == 0xffff, "");
210
211 static_assert(UINT32_C(0) == 0, "");
212 static_assert(UINT32_C(0xffffffff) == 0xffffffff, "");
213
214 static_assert(UINT64_C(0) == 0, "");
215 static_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
224 static_assert(INTMAX_C(0) == 0, "");
225 static_assert(INTMAX_C(-0xffffffffffffffff - 1) == -0xffffffffffffffff - 1, "");
226 static_assert(INTMAX_C(0x7fffffffffffffff) == 0x7fffffffffffffff, "");
227
228 static_assert(UINTMAX_C(0) == 0, "");
229 static_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
check_format_specifiers(void)278 static 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
324 BEGIN_TEST_CASE(c_format_specifiers)
325 RUN_TEST(check_format_specifiers)
326 END_TEST_CASE(c_format_specifiers)
327