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 <inttypes.h> 6#include <limits.h> 7#include <signal.h> 8#include <stdint.h> 9#include <wchar.h> 10 11#include <fbl/type_support.h> 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// Check maximums. 105#define CHECK_MAX_TYPE(type, TYPE, max_t, MAX) \ 106 ((max_t)TYPE##_MAX == (MAX >> (CHAR_BIT * (sizeof(max_t) - sizeof(type))))) 107 108#define CHECK_MAX_UNSIGNED(type, TYPE) CHECK_MAX_TYPE(type, TYPE, uintmax_t, UINTMAX_MAX) 109#define CHECK_MAX_SIGNED(type, TYPE) CHECK_MAX_TYPE(type, TYPE, intmax_t, INTMAX_MAX) 110 111#define CHECK_MAX(type, TYPE) static_assert(fbl::is_signed<type>::value ? CHECK_MAX_SIGNED(type, TYPE) : CHECK_MAX_UNSIGNED(type, TYPE), ""); 112 113CHECK_MAX(int8_t, INT8); 114CHECK_MAX(int16_t, INT16); 115CHECK_MAX(int32_t, INT32); 116CHECK_MAX(int64_t, INT64); 117CHECK_MAX(uint8_t, UINT8); 118CHECK_MAX(uint16_t, UINT16); 119CHECK_MAX(uint32_t, UINT32); 120CHECK_MAX(uint64_t, UINT64); 121 122CHECK_MAX(int_least8_t, INT_LEAST8); 123CHECK_MAX(int_least16_t, INT_LEAST16); 124CHECK_MAX(int_least32_t, INT_LEAST32); 125CHECK_MAX(int_least64_t, INT_LEAST64); 126CHECK_MAX(uint_least8_t, UINT_LEAST8); 127CHECK_MAX(uint_least16_t, UINT_LEAST16); 128CHECK_MAX(uint_least32_t, UINT_LEAST32); 129CHECK_MAX(uint_least64_t, UINT_LEAST64); 130 131CHECK_MAX(int_fast8_t, INT_FAST8); 132CHECK_MAX(int_fast16_t, INT_FAST16); 133CHECK_MAX(int_fast32_t, INT_FAST32); 134CHECK_MAX(int_fast64_t, INT_FAST64); 135CHECK_MAX(uint_fast8_t, UINT_FAST8); 136CHECK_MAX(uint_fast16_t, UINT_FAST16); 137CHECK_MAX(uint_fast32_t, UINT_FAST32); 138CHECK_MAX(uint_fast64_t, UINT_FAST64); 139 140CHECK_MAX(intptr_t, INTPTR); 141CHECK_MAX(uintptr_t, UINTPTR); 142 143CHECK_MAX(intmax_t, INTMAX); 144CHECK_MAX(uintmax_t, UINTMAX); 145 146CHECK_MAX(ptrdiff_t, PTRDIFF); 147CHECK_MAX(size_t, SIZE); 148CHECK_MAX(wchar_t, WCHAR); 149 150CHECK_MAX(sig_atomic_t, SIG_ATOMIC); 151 152// Check minimums. 153#define CHECK_MIN_TYPE(type, TYPE) \ 154 ((intmax_t)TYPE##_MIN == (INTMAX_MIN >> (CHAR_BIT * (sizeof(intmax_t) - sizeof(type))))) 155 156#define CHECK_MIN(type, TYPE) static_assert(CHECK_MIN_TYPE(type, TYPE), "") 157 158CHECK_MIN(int8_t, INT8); 159CHECK_MIN(int16_t, INT16); 160CHECK_MIN(int32_t, INT32); 161CHECK_MIN(int64_t, INT64); 162 163CHECK_MIN(int_least8_t, INT_LEAST8); 164CHECK_MIN(int_least16_t, INT_LEAST16); 165CHECK_MIN(int_least32_t, INT_LEAST32); 166CHECK_MIN(int_least64_t, INT_LEAST64); 167 168CHECK_MIN(int_fast8_t, INT_FAST8); 169CHECK_MIN(int_fast16_t, INT_FAST16); 170CHECK_MIN(int_fast32_t, INT_FAST32); 171CHECK_MIN(int_fast64_t, INT_FAST64); 172 173CHECK_MIN(intptr_t, INTPTR); 174 175CHECK_MIN(intmax_t, INTMAX); 176 177CHECK_MIN(ptrdiff_t, PTRDIFF); 178static_assert(fbl::is_signed<wchar_t>::value ? CHECK_MIN_TYPE(wchar_t, WCHAR) : (WCHAR_MIN == 0), ""); 179 180static_assert(fbl::is_signed<sig_atomic_t>::value ? CHECK_MIN_TYPE(sig_atomic_t, SIG_ATOMIC) : (SIG_ATOMIC_MIN == 0), ""); 181 182// The INTN_C and UINTN_C macros expand into integer constants 183// "corresponding to the type int_leastN_t" and "uint_leastN_t" 184// respectively. 185 186static_assert(INT8_C(0) == fbl::integral_constant<int_least8_t, 0>::value, ""); 187static_assert(INT8_C(-0x7f - 1) == fbl::integral_constant<int_least8_t, -0x7f - 1>::value, ""); 188static_assert(INT8_C(0x7f) == fbl::integral_constant<int_least8_t, 0x7f>::value, ""); 189 190static_assert(INT16_C(0) == fbl::integral_constant<int_least16_t, 0>::value, ""); 191static_assert(INT16_C(-0x7fff - 1) == fbl::integral_constant<int_least16_t, -0x7fff - 1>::value, ""); 192static_assert(INT16_C(0x7fff) == fbl::integral_constant<int_least16_t, 0x7fff>::value, ""); 193 194static_assert(INT32_C(0) == fbl::integral_constant<int_least32_t, 0>::value, ""); 195static_assert(INT32_C(-0x7fffffff - 1) == fbl::integral_constant<int_least32_t, -0x7fffffff - 1>::value, ""); 196static_assert(INT32_C(0x7fffffff) == fbl::integral_constant<int_least32_t, 0x7fffffff>::value, ""); 197 198static_assert(INT64_C(0) == fbl::integral_constant<int_least64_t, 0>::value, ""); 199static_assert(INT64_C(-0x7fffffffffffffff - 1) == fbl::integral_constant<int_least64_t, -0x7fffffffffffffff - 1>::value, ""); 200static_assert(INT64_C(0x7fffffffffffffff) == fbl::integral_constant<int_least64_t, 0x7fffffffffffffff>::value, ""); 201 202 203static_assert(UINT8_C(0) == fbl::integral_constant<uint_least8_t, 0>::value, ""); 204static_assert(UINT8_C(0xff) == fbl::integral_constant<uint_least8_t, 0xff>::value, ""); 205 206static_assert(UINT16_C(0) == fbl::integral_constant<uint_least16_t, 0>::value, ""); 207static_assert(UINT16_C(0xffff) == fbl::integral_constant<uint_least16_t, 0xffff>::value, ""); 208 209static_assert(UINT32_C(0) == fbl::integral_constant<uint_least32_t, 0>::value, ""); 210static_assert(UINT32_C(0xffffffff) == fbl::integral_constant<uint_least32_t, 0xffffffff>::value, ""); 211 212static_assert(UINT64_C(0) == fbl::integral_constant<uint_least64_t, 0>::value, ""); 213static_assert(UINT64_C(0xffffffffffffffff) == fbl::integral_constant<uint_least64_t, 0xffffffffffffffff>::value, ""); 214 215 216// Unlike the above, the INTMAX_C and UINTMAX_C macros explicitly 217// produce values of type intmax_t and uintmax_t respectively, not 218// just compatible values. 219 220static_assert(fbl::is_same<intmax_t, decltype(INTMAX_C(0))>::value, ""); 221static_assert(fbl::is_same<intmax_t, decltype(INTMAX_C(-0x7fffffffffffffff - 1))>::value, ""); 222static_assert(fbl::is_same<intmax_t, decltype(INTMAX_C(0x7fffffffffffffff))>::value, ""); 223static_assert(INTMAX_C(0) == fbl::integral_constant<intmax_t, 0>::value, ""); 224static_assert(INTMAX_C(-0xffffffffffffffff - 1) == fbl::integral_constant<intmax_t, -0xffffffffffffffff - 1>::value, ""); 225static_assert(INTMAX_C(0x7fffffffffffffff) == fbl::integral_constant<intmax_t, 0x7fffffffffffffff>::value, ""); 226 227static_assert(fbl::is_same<uintmax_t, decltype(UINTMAX_C(0))>::value, ""); 228static_assert(fbl::is_same<uintmax_t, decltype(UINTMAX_C(0xffffffffffffffff))>::value, ""); 229static_assert(UINTMAX_C(0) == fbl::integral_constant<uintmax_t, 0>::value, ""); 230static_assert(UINTMAX_C(0xffffffffffffffff) == fbl::integral_constant<uintmax_t, 0xffffffffffffffff>::value, ""); 231 232 233// Check PRI* and SCN* format strings. 234#define LAST(fmt) (fmt[strlen(fmt) - 1]) 235 236// Signed format specifiers. 237#define CHECK_d(fmt) EXPECT_EQ(LAST(fmt), 'd', "incorrect format specifier") 238#define CHECK_i(fmt) EXPECT_EQ(LAST(fmt), 'i', "incorrect format specifier") 239 240// Unsigned format specifiers. Note that X is only used by printf, and 241// not also by scanf. 242#define CHECK_o(fmt) EXPECT_EQ(LAST(fmt), 'o', "incorrect format specifier") 243#define CHECK_u(fmt) EXPECT_EQ(LAST(fmt), 'u', "incorrect format specifier") 244#define CHECK_x(fmt) EXPECT_EQ(LAST(fmt), 'x', "incorrect format specifier") 245#define CHECK_X(fmt) EXPECT_EQ(LAST(fmt), 'X', "incorrect format specifier") 246 247#define CHECK_FORMAT_STRINGS(pri, scn, pcheck, scheck, type, max) do { \ 248 pcheck(pri); \ 249 scheck(scn); \ 250 char buf[256] = {0}; \ 251 ASSERT_GT(snprintf(buf, sizeof(buf), "%" pri, (type)max), 1); \ 252 type n = (type)0; \ 253 ASSERT_EQ(sscanf(buf, "%" scn, &n), 1); \ 254 ASSERT_EQ(n, max); \ 255 } while (0) 256 257#define CHECK_SIGNED_FORMATS(size, type, max) do { \ 258 CHECK_FORMAT_STRINGS(PRId ## size, SCNd ## size, CHECK_d, CHECK_d, type, max); \ 259 CHECK_FORMAT_STRINGS(PRIi ## size, SCNi ## size, CHECK_i, CHECK_i, type, max); \ 260 } while (0) 261 262// Since X is not used by scanf (only x), the last line has PRIX but 263// SCNx (upper and lower case). 264#define CHECK_UNSIGNED_FORMATS(size, type, max) do { \ 265 CHECK_FORMAT_STRINGS(PRIo ## size, SCNo ## size, CHECK_o, CHECK_o, type, max); \ 266 CHECK_FORMAT_STRINGS(PRIu ## size, SCNu ## size, CHECK_u, CHECK_u, type, max); \ 267 CHECK_FORMAT_STRINGS(PRIx ## size, SCNx ## size, CHECK_x, CHECK_x, type, max); \ 268 CHECK_FORMAT_STRINGS(PRIX ## size, SCNx ## size, CHECK_X, CHECK_x, type, max); \ 269 } while (0) 270 271#define CHECK_FORMATS(size, type, max) do { \ 272 if (fbl::is_signed<type>::value) { \ 273 CHECK_SIGNED_FORMATS(size, type, max); \ 274 } else { \ 275 CHECK_UNSIGNED_FORMATS(size, type, max); \ 276 } \ 277 } while (0) 278 279static bool check_format_specifiers(void) { 280 BEGIN_TEST; 281 282 CHECK_FORMATS(8, int8_t, INT8_MAX); 283 CHECK_FORMATS(16, int16_t, INT16_MAX); 284 CHECK_FORMATS(32, int32_t, INT32_MAX); 285 CHECK_FORMATS(64, int64_t, INT64_MAX); 286 CHECK_FORMATS(8, uint8_t, UINT8_MAX); 287 CHECK_FORMATS(16, uint16_t, UINT16_MAX); 288 CHECK_FORMATS(32, uint32_t, UINT32_MAX); 289 CHECK_FORMATS(64, uint64_t, UINT64_MAX); 290 291 CHECK_FORMATS(FAST8, int_fast8_t, INT_FAST8_MAX); 292 CHECK_FORMATS(FAST16, int_fast16_t, INT_FAST16_MAX); 293 CHECK_FORMATS(FAST32, int_fast32_t, INT_FAST32_MAX); 294 CHECK_FORMATS(FAST64, int_fast64_t, INT_FAST64_MAX); 295 CHECK_FORMATS(FAST8, uint_fast8_t, UINT_FAST8_MAX); 296 CHECK_FORMATS(FAST16, uint_fast16_t, UINT_FAST16_MAX); 297 CHECK_FORMATS(FAST32, uint_fast32_t, UINT_FAST32_MAX); 298 CHECK_FORMATS(FAST64, uint_fast64_t, UINT_FAST64_MAX); 299 300 CHECK_FORMATS(LEAST8, int_least8_t, INT_LEAST8_MAX); 301 CHECK_FORMATS(LEAST16, int_least16_t, INT_LEAST16_MAX); 302 CHECK_FORMATS(LEAST32, int_least32_t, INT_LEAST32_MAX); 303 CHECK_FORMATS(LEAST64, int_least64_t, INT_LEAST64_MAX); 304 CHECK_FORMATS(LEAST8, uint_least8_t, UINT_LEAST8_MAX); 305 CHECK_FORMATS(LEAST16, uint_least16_t, UINT_LEAST16_MAX); 306 CHECK_FORMATS(LEAST32, uint_least32_t, UINT_LEAST32_MAX); 307 CHECK_FORMATS(LEAST64, uint_least64_t, UINT_LEAST64_MAX); 308 309 CHECK_FORMATS(PTR, intptr_t, INTPTR_MAX); 310 CHECK_FORMATS(PTR, uintptr_t, UINTPTR_MAX); 311 312 // Note that these are definined in addition to %j 313 CHECK_FORMATS(MAX, intmax_t, INTMAX_MAX); 314 CHECK_FORMATS(MAX, uintmax_t, UINTMAX_MAX); 315 316 // ptrdiff_t is simply %t. 317 // size_t is simply %z. 318 // wchar_t is simply %sl. 319 320 // No particular format specifier or macro is defined for sig_atomic_t. 321 322 END_TEST; 323} 324 325BEGIN_TEST_CASE(format_specifiers) 326RUN_TEST(check_format_specifiers) 327END_TEST_CASE(format_specifiers) 328 329int main(int argc, char** argv) { 330 return unittest_run_all_tests(argc, argv) ? 0 : -1; 331} 332