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