kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

commit d51c0ff8fbdc514827366d5bed17e1352c39cbb5
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Thu,  7 May 2026 08:49:40 -0700

cfree freestanding headers

Diffstat:
Abuiltins.md | 135+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ainclude/float.h | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ainclude/iso646.h | 17+++++++++++++++++
Ainclude/limits.h | 50++++++++++++++++++++++++++++++++++++++++++++++++++
Ainclude/stdalign.h | 11+++++++++++
Ainclude/stdarg.h | 15+++++++++++++++
Ainclude/stdbool.h | 11+++++++++++
Ainclude/stddef.h | 23+++++++++++++++++++++++
Ainclude/stdint.h | 147+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ainclude/stdnoreturn.h | 7+++++++
Atest/smoke.c | 104+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11 files changed, 596 insertions(+), 0 deletions(-)

diff --git a/builtins.md b/builtins.md @@ -0,0 +1,135 @@ +# Compiler builtins used by cfree + +Every value in cfree's freestanding headers is delegated to the compiler. +This file lists what we rely on, grouped by header. All names below are +provided by both GCC (≥ 4.x) and Clang. They are predefined macros unless +marked **(builtin)**, in which case they are intrinsic identifiers usable +in expressions. + +--- + +## `<float.h>` + +Mostly a 1-to-1 passthrough of `__*__` macros to their C11 spellings. + +| C11 macro | Compiler source | +| ------------------ | ------------------------------------- | +| `FLT_ROUNDS` | `__builtin_flt_rounds()` **(builtin)** — runtime rounding mode | +| `FLT_EVAL_METHOD` | `__FLT_EVAL_METHOD__` | +| `FLT_RADIX` | `__FLT_RADIX__` | +| `*_HAS_SUBNORM` | `__{FLT,DBL,LDBL}_HAS_DENORM__` | +| `*_MANT_DIG` | `__{FLT,DBL,LDBL}_MANT_DIG__` | +| `*_DECIMAL_DIG` | `__{FLT,DBL,LDBL}_DECIMAL_DIG__` | +| `DECIMAL_DIG` | `__DECIMAL_DIG__` | +| `*_DIG` | `__{FLT,DBL,LDBL}_DIG__` | +| `*_MIN_EXP` | `__{FLT,DBL,LDBL}_MIN_EXP__` | +| `*_MIN_10_EXP` | `__{FLT,DBL,LDBL}_MIN_10_EXP__` | +| `*_MAX_EXP` | `__{FLT,DBL,LDBL}_MAX_EXP__` | +| `*_MAX_10_EXP` | `__{FLT,DBL,LDBL}_MAX_10_EXP__` | +| `*_MAX` | `__{FLT,DBL,LDBL}_MAX__` | +| `*_EPSILON` | `__{FLT,DBL,LDBL}_EPSILON__` | +| `*_MIN` | `__{FLT,DBL,LDBL}_MIN__` | +| `*_TRUE_MIN` | `__{FLT,DBL,LDBL}_DENORM_MIN__` | + +Note the rename: C11 uses `SUBNORM`/`TRUE_MIN`; GCC/Clang use `DENORM`/`DENORM_MIN`. + +--- + +## `<limits.h>` + +| C11 macro | Compiler source | +| ------------ | --------------------------------------------------------- | +| `CHAR_BIT` | `__CHAR_BIT__` | +| `SCHAR_MAX` | `__SCHAR_MAX__` | +| `CHAR_*` | derived from `__CHAR_UNSIGNED__` (defined ⇒ char is unsigned) | +| `SHRT_MAX` | `__SHRT_MAX__` | +| `INT_MAX` | `__INT_MAX__` | +| `LONG_MAX` | `__LONG_MAX__` | +| `LLONG_MAX` | `__LONG_LONG_MAX__` | + +`*_MIN` / unsigned `*_MAX` are derived arithmetically from the signed `*_MAX` +(C11 guarantees two's-complement-or-equivalent representations make this +exact). `MB_LEN_MAX` is *not* compiler-provided — we hardcode `1`. + +--- + +## `<stddef.h>` + +| C11 name | Compiler source | +| ------------ | ------------------------------------- | +| `ptrdiff_t` | `__PTRDIFF_TYPE__` | +| `size_t` | `__SIZE_TYPE__` | +| `wchar_t` | `__WCHAR_TYPE__` (C only; keyword in C++) | +| `offsetof` | `__builtin_offsetof(t, m)` **(builtin)** | +| `NULL` | `((void*)0)` — not compiler-provided | +| `max_align_t`| no builtin — a struct of `long long` + `long double` is the conventional definition | + +--- + +## `<stdint.h>` + +For each width N ∈ {8, 16, 32, 64} the compiler provides a *type*, a *max*, +and a *constant-suffix* macro. We pass them through unchanged. + +### Types +- `__INT{N}_TYPE__`, `__UINT{N}_TYPE__` +- `__INT_LEAST{N}_TYPE__`, `__UINT_LEAST{N}_TYPE__` +- `__INT_FAST{N}_TYPE__`, `__UINT_FAST{N}_TYPE__` +- `__INTPTR_TYPE__`, `__UINTPTR_TYPE__` +- `__INTMAX_TYPE__`, `__UINTMAX_TYPE__` + +### Limits +- `__INT{N}_MAX__`, `__UINT{N}_MAX__` +- `__INT_LEAST{N}_MAX__`, `__UINT_LEAST{N}_MAX__` +- `__INT_FAST{N}_MAX__`, `__UINT_FAST{N}_MAX__` +- `__INTPTR_MAX__`, `__UINTPTR_MAX__` +- `__INTMAX_MAX__`, `__UINTMAX_MAX__` +- `__PTRDIFF_MAX__`, `__SIZE_MAX__` +- `__WCHAR_MAX__`, `__WCHAR_MIN__` +- `__WINT_MAX__`, `__WINT_MIN__` +- `__SIG_ATOMIC_MAX__`, `__SIG_ATOMIC_MIN__` + +`*_MIN` for signed types is derived as `(-MAX - 1)`. + +### Constant macros (function-like) +- `__INT{N}_C(c)`, `__UINT{N}_C(c)` — append the literal suffix appropriate + for the corresponding `int_least{N}_t` (e.g. `__INT64_C(1)` → `1L` or `1LL` + depending on target). +- `__INTMAX_C(c)`, `__UINTMAX_C(c)` — same for `intmax_t`. + +--- + +## `<stdarg.h>` + +Entirely compiler-supplied — varargs ABI is too target-specific to express +in portable C. + +| C11 name | Builtin | +| ---------- | ----------------------------- | +| `va_list` | `__builtin_va_list` (type) | +| `va_start` | `__builtin_va_start(ap, last)`| +| `va_arg` | `__builtin_va_arg(ap, type)` | +| `va_end` | `__builtin_va_end(ap)` | +| `va_copy` | `__builtin_va_copy(dst, src)` | + +--- + +## `<stdalign.h>`, `<stdbool.h>`, `<stdnoreturn.h>`, `<iso646.h>` + +No builtins. These headers are pure preprocessor aliases for C11 keywords +(`_Alignas`, `_Alignof`, `_Bool`, `_Noreturn`) and operator spellings. + +--- + +## Discovery + +To enumerate every macro a particular compiler predefines on the current +target: + +```sh +cc -dM -E -x c /dev/null | sort +``` + +The full set is target- and version-dependent; the macros above are the +ones cfree relies on, and all are present on every GCC/Clang target we +target. diff --git a/include/float.h b/include/float.h @@ -0,0 +1,76 @@ +/* float.h -- C11 7.7 -- Characteristics of floating types */ +#ifndef CFREE_FLOAT_H +#define CFREE_FLOAT_H + +/* Rounding mode, FLT_EVAL_METHOD, and the radix are target-/runtime-dependent + and predefined by the compiler. */ +#define FLT_ROUNDS (__builtin_flt_rounds()) +#define FLT_EVAL_METHOD __FLT_EVAL_METHOD__ +#define FLT_RADIX __FLT_RADIX__ + +/* Subnormal support (C11 added). 1 = supports subnormals, 0 = does not, + -1 = indeterminable. */ +#define FLT_HAS_SUBNORM __FLT_HAS_DENORM__ +#define DBL_HAS_SUBNORM __DBL_HAS_DENORM__ +#define LDBL_HAS_SUBNORM __LDBL_HAS_DENORM__ + +/* Number of base-FLT_RADIX mantissa digits. */ +#define FLT_MANT_DIG __FLT_MANT_DIG__ +#define DBL_MANT_DIG __DBL_MANT_DIG__ +#define LDBL_MANT_DIG __LDBL_MANT_DIG__ + +/* Number of decimal digits, n, such that any floating value with p radix-b + digits can be rounded into a decimal with n digits and back without loss. */ +#define FLT_DECIMAL_DIG __FLT_DECIMAL_DIG__ +#define DBL_DECIMAL_DIG __DBL_DECIMAL_DIG__ +#define LDBL_DECIMAL_DIG __LDBL_DECIMAL_DIG__ +#define DECIMAL_DIG __DECIMAL_DIG__ + +/* Number of decimal digits q such that any number with q decimals can be + rounded into the type and back unchanged. */ +#define FLT_DIG __FLT_DIG__ +#define DBL_DIG __DBL_DIG__ +#define LDBL_DIG __LDBL_DIG__ + +/* Minimum negative integer e such that FLT_RADIX**(e-1) is a normalized + value. */ +#define FLT_MIN_EXP __FLT_MIN_EXP__ +#define DBL_MIN_EXP __DBL_MIN_EXP__ +#define LDBL_MIN_EXP __LDBL_MIN_EXP__ + +/* Minimum negative integer such that 10 raised to it is a normalized value. */ +#define FLT_MIN_10_EXP __FLT_MIN_10_EXP__ +#define DBL_MIN_10_EXP __DBL_MIN_10_EXP__ +#define LDBL_MIN_10_EXP __LDBL_MIN_10_EXP__ + +/* Maximum integer e such that FLT_RADIX**(e-1) is representable. */ +#define FLT_MAX_EXP __FLT_MAX_EXP__ +#define DBL_MAX_EXP __DBL_MAX_EXP__ +#define LDBL_MAX_EXP __LDBL_MAX_EXP__ + +/* Maximum integer such that 10 raised to it is representable. */ +#define FLT_MAX_10_EXP __FLT_MAX_10_EXP__ +#define DBL_MAX_10_EXP __DBL_MAX_10_EXP__ +#define LDBL_MAX_10_EXP __LDBL_MAX_10_EXP__ + +/* Maximum representable finite value. */ +#define FLT_MAX __FLT_MAX__ +#define DBL_MAX __DBL_MAX__ +#define LDBL_MAX __LDBL_MAX__ + +/* Difference between 1 and the least value greater than 1. */ +#define FLT_EPSILON __FLT_EPSILON__ +#define DBL_EPSILON __DBL_EPSILON__ +#define LDBL_EPSILON __LDBL_EPSILON__ + +/* Minimum normalized positive value. */ +#define FLT_MIN __FLT_MIN__ +#define DBL_MIN __DBL_MIN__ +#define LDBL_MIN __LDBL_MIN__ + +/* Minimum positive value (may be subnormal). C11 added. */ +#define FLT_TRUE_MIN __FLT_DENORM_MIN__ +#define DBL_TRUE_MIN __DBL_DENORM_MIN__ +#define LDBL_TRUE_MIN __LDBL_DENORM_MIN__ + +#endif diff --git a/include/iso646.h b/include/iso646.h @@ -0,0 +1,17 @@ +/* iso646.h -- C11 7.9 -- Alternative spellings */ +#ifndef CFREE_ISO646_H +#define CFREE_ISO646_H + +#define and && +#define and_eq &= +#define bitand & +#define bitor | +#define compl ~ +#define not ! +#define not_eq != +#define or || +#define or_eq |= +#define xor ^ +#define xor_eq ^= + +#endif diff --git a/include/limits.h b/include/limits.h @@ -0,0 +1,50 @@ +/* limits.h -- C11 7.10 -- Sizes of integer types */ +#ifndef CFREE_LIMITS_H +#define CFREE_LIMITS_H + +/* Number of bits in a byte. C11 mandates value >= 8; on every supported + GCC/Clang target this is 8. */ +#define CHAR_BIT __CHAR_BIT__ + +/* Maximum length of a multibyte character. C11 requires this to be >= 1. + The value depends on the locale; freestanding code has no locale facility, + so 1 is the safest portable answer. (Compilers do not predefine this.) */ +#define MB_LEN_MAX 1 + +/* signed char */ +#define SCHAR_MAX __SCHAR_MAX__ +#define SCHAR_MIN (-SCHAR_MAX - 1) + +/* unsigned char */ +#define UCHAR_MAX (SCHAR_MAX * 2 + 1) + +/* plain char -- signedness is implementation-defined */ +#ifdef __CHAR_UNSIGNED__ +# define CHAR_MIN 0 +# define CHAR_MAX UCHAR_MAX +#else +# define CHAR_MIN SCHAR_MIN +# define CHAR_MAX SCHAR_MAX +#endif + +/* short */ +#define SHRT_MAX __SHRT_MAX__ +#define SHRT_MIN (-SHRT_MAX - 1) +#define USHRT_MAX (SHRT_MAX * 2 + 1) + +/* int */ +#define INT_MAX __INT_MAX__ +#define INT_MIN (-INT_MAX - 1) +#define UINT_MAX (INT_MAX * 2U + 1U) + +/* long */ +#define LONG_MAX __LONG_MAX__ +#define LONG_MIN (-LONG_MAX - 1L) +#define ULONG_MAX (LONG_MAX * 2UL + 1UL) + +/* long long */ +#define LLONG_MAX __LONG_LONG_MAX__ +#define LLONG_MIN (-LLONG_MAX - 1LL) +#define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL) + +#endif diff --git a/include/stdalign.h b/include/stdalign.h @@ -0,0 +1,11 @@ +/* stdalign.h -- C11 7.15 -- Alignment */ +#ifndef CFREE_STDALIGN_H +#define CFREE_STDALIGN_H + +#define alignas _Alignas +#define alignof _Alignof + +#define __alignas_is_defined 1 +#define __alignof_is_defined 1 + +#endif diff --git a/include/stdarg.h b/include/stdarg.h @@ -0,0 +1,15 @@ +/* stdarg.h -- C11 7.16 -- Variable arguments */ +#ifndef CFREE_STDARG_H +#define CFREE_STDARG_H + +typedef __builtin_va_list va_list; + +#define va_start(ap, last) __builtin_va_start(ap, last) +#define va_arg(ap, type) __builtin_va_arg(ap, type) +#define va_end(ap) __builtin_va_end(ap) +#define va_copy(dst, src) __builtin_va_copy(dst, src) + +/* Required in C11 for use with vprintf-family in <stdio.h>; harmless here. */ +typedef __builtin_va_list __gnuc_va_list; + +#endif diff --git a/include/stdbool.h b/include/stdbool.h @@ -0,0 +1,11 @@ +/* stdbool.h -- C11 7.18 -- Boolean type and values */ +#ifndef CFREE_STDBOOL_H +#define CFREE_STDBOOL_H + +#define bool _Bool +#define true 1 +#define false 0 + +#define __bool_true_false_are_defined 1 + +#endif diff --git a/include/stddef.h b/include/stddef.h @@ -0,0 +1,23 @@ +/* stddef.h -- C11 7.19 -- Common definitions */ +#ifndef CFREE_STDDEF_H +#define CFREE_STDDEF_H + +typedef __PTRDIFF_TYPE__ ptrdiff_t; +typedef __SIZE_TYPE__ size_t; +typedef __WCHAR_TYPE__ wchar_t; + +/* C11 7.19: max_align_t is an object type whose alignment is the greatest + fundamental alignment. A struct holding the widest scalar types is the + conventional definition and matches what GCC/Clang use in their own + stddef.h. */ +typedef struct { + long long __cfree_ll; + long double __cfree_ld; +} max_align_t; + +#undef NULL +#define NULL ((void *)0) + +#define offsetof(type, member) __builtin_offsetof(type, member) + +#endif diff --git a/include/stdint.h b/include/stdint.h @@ -0,0 +1,147 @@ +/* stdint.h -- C11 7.20 -- Integer types of specified widths */ +#ifndef CFREE_STDINT_H +#define CFREE_STDINT_H + +/* ------------------------------------------------------------------ */ +/* 7.20.1.1 Exact-width integer types */ +/* ------------------------------------------------------------------ */ +typedef __INT8_TYPE__ int8_t; +typedef __INT16_TYPE__ int16_t; +typedef __INT32_TYPE__ int32_t; +typedef __INT64_TYPE__ int64_t; + +typedef __UINT8_TYPE__ uint8_t; +typedef __UINT16_TYPE__ uint16_t; +typedef __UINT32_TYPE__ uint32_t; +typedef __UINT64_TYPE__ uint64_t; + +/* ------------------------------------------------------------------ */ +/* 7.20.1.2 Minimum-width integer types */ +/* ------------------------------------------------------------------ */ +typedef __INT_LEAST8_TYPE__ int_least8_t; +typedef __INT_LEAST16_TYPE__ int_least16_t; +typedef __INT_LEAST32_TYPE__ int_least32_t; +typedef __INT_LEAST64_TYPE__ int_least64_t; + +typedef __UINT_LEAST8_TYPE__ uint_least8_t; +typedef __UINT_LEAST16_TYPE__ uint_least16_t; +typedef __UINT_LEAST32_TYPE__ uint_least32_t; +typedef __UINT_LEAST64_TYPE__ uint_least64_t; + +/* ------------------------------------------------------------------ */ +/* 7.20.1.3 Fastest minimum-width integer types */ +/* ------------------------------------------------------------------ */ +typedef __INT_FAST8_TYPE__ int_fast8_t; +typedef __INT_FAST16_TYPE__ int_fast16_t; +typedef __INT_FAST32_TYPE__ int_fast32_t; +typedef __INT_FAST64_TYPE__ int_fast64_t; + +typedef __UINT_FAST8_TYPE__ uint_fast8_t; +typedef __UINT_FAST16_TYPE__ uint_fast16_t; +typedef __UINT_FAST32_TYPE__ uint_fast32_t; +typedef __UINT_FAST64_TYPE__ uint_fast64_t; + +/* ------------------------------------------------------------------ */ +/* 7.20.1.4 Integer types capable of holding object pointers */ +/* ------------------------------------------------------------------ */ +typedef __INTPTR_TYPE__ intptr_t; +typedef __UINTPTR_TYPE__ uintptr_t; + +/* ------------------------------------------------------------------ */ +/* 7.20.1.5 Greatest-width integer types */ +/* ------------------------------------------------------------------ */ +typedef __INTMAX_TYPE__ intmax_t; +typedef __UINTMAX_TYPE__ uintmax_t; + +/* ------------------------------------------------------------------ */ +/* 7.20.2 Limits of specified-width integer types */ +/* ------------------------------------------------------------------ */ + +/* exact-width */ +#define INT8_MAX __INT8_MAX__ +#define INT16_MAX __INT16_MAX__ +#define INT32_MAX __INT32_MAX__ +#define INT64_MAX __INT64_MAX__ +#define INT8_MIN (-INT8_MAX - 1) +#define INT16_MIN (-INT16_MAX - 1) +#define INT32_MIN (-INT32_MAX - 1) +#define INT64_MIN (-INT64_MAX - 1) +#define UINT8_MAX __UINT8_MAX__ +#define UINT16_MAX __UINT16_MAX__ +#define UINT32_MAX __UINT32_MAX__ +#define UINT64_MAX __UINT64_MAX__ + +/* minimum-width */ +#define INT_LEAST8_MAX __INT_LEAST8_MAX__ +#define INT_LEAST16_MAX __INT_LEAST16_MAX__ +#define INT_LEAST32_MAX __INT_LEAST32_MAX__ +#define INT_LEAST64_MAX __INT_LEAST64_MAX__ +#define INT_LEAST8_MIN (-INT_LEAST8_MAX - 1) +#define INT_LEAST16_MIN (-INT_LEAST16_MAX - 1) +#define INT_LEAST32_MIN (-INT_LEAST32_MAX - 1) +#define INT_LEAST64_MIN (-INT_LEAST64_MAX - 1) +#define UINT_LEAST8_MAX __UINT_LEAST8_MAX__ +#define UINT_LEAST16_MAX __UINT_LEAST16_MAX__ +#define UINT_LEAST32_MAX __UINT_LEAST32_MAX__ +#define UINT_LEAST64_MAX __UINT_LEAST64_MAX__ + +/* fastest minimum-width */ +#define INT_FAST8_MAX __INT_FAST8_MAX__ +#define INT_FAST16_MAX __INT_FAST16_MAX__ +#define INT_FAST32_MAX __INT_FAST32_MAX__ +#define INT_FAST64_MAX __INT_FAST64_MAX__ +#define INT_FAST8_MIN (-INT_FAST8_MAX - 1) +#define INT_FAST16_MIN (-INT_FAST16_MAX - 1) +#define INT_FAST32_MIN (-INT_FAST32_MAX - 1) +#define INT_FAST64_MIN (-INT_FAST64_MAX - 1) +#define UINT_FAST8_MAX __UINT_FAST8_MAX__ +#define UINT_FAST16_MAX __UINT_FAST16_MAX__ +#define UINT_FAST32_MAX __UINT_FAST32_MAX__ +#define UINT_FAST64_MAX __UINT_FAST64_MAX__ + +/* pointer-holding */ +#define INTPTR_MAX __INTPTR_MAX__ +#define INTPTR_MIN (-INTPTR_MAX - 1) +#define UINTPTR_MAX __UINTPTR_MAX__ + +/* greatest-width */ +#define INTMAX_MAX __INTMAX_MAX__ +#define INTMAX_MIN (-INTMAX_MAX - 1) +#define UINTMAX_MAX __UINTMAX_MAX__ + +/* ------------------------------------------------------------------ */ +/* 7.20.3 Limits of other integer types defined in <stddef.h> etc. */ +/* ------------------------------------------------------------------ */ +#define PTRDIFF_MAX __PTRDIFF_MAX__ +#define PTRDIFF_MIN (-PTRDIFF_MAX - 1) + +#define SIZE_MAX __SIZE_MAX__ + +#define WCHAR_MAX __WCHAR_MAX__ +#define WCHAR_MIN __WCHAR_MIN__ + +#define WINT_MAX __WINT_MAX__ +#define WINT_MIN __WINT_MIN__ + +/* sig_atomic_t bounds: defined in <signal.h>, which is not freestanding, + but the macros must still be exposed by <stdint.h>. */ +#define SIG_ATOMIC_MAX __SIG_ATOMIC_MAX__ +#define SIG_ATOMIC_MIN __SIG_ATOMIC_MIN__ + +/* ------------------------------------------------------------------ */ +/* 7.20.4 Macros for integer constants */ +/* ------------------------------------------------------------------ */ +#define INT8_C(c) __INT8_C(c) +#define INT16_C(c) __INT16_C(c) +#define INT32_C(c) __INT32_C(c) +#define INT64_C(c) __INT64_C(c) + +#define UINT8_C(c) __UINT8_C(c) +#define UINT16_C(c) __UINT16_C(c) +#define UINT32_C(c) __UINT32_C(c) +#define UINT64_C(c) __UINT64_C(c) + +#define INTMAX_C(c) __INTMAX_C(c) +#define UINTMAX_C(c) __UINTMAX_C(c) + +#endif diff --git a/include/stdnoreturn.h b/include/stdnoreturn.h @@ -0,0 +1,7 @@ +/* stdnoreturn.h -- C11 7.23 -- _Noreturn convenience macro */ +#ifndef CFREE_STDNORETURN_H +#define CFREE_STDNORETURN_H + +#define noreturn _Noreturn + +#endif diff --git a/test/smoke.c b/test/smoke.c @@ -0,0 +1,104 @@ +/* Smoke test: every freestanding header should parse and expose its + required macros / typedefs. Compile with: + cc -std=c11 -ffreestanding -nostdinc -Iinclude -Wall -Wextra \ + -Wpedantic -c test/smoke.c -o /tmp/smoke.o + No link step -- freestanding has no startup, no libc. */ + +#include <float.h> +#include <iso646.h> +#include <limits.h> +#include <stdalign.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <stdnoreturn.h> + +/* ---- compile-time assertions over the contracts ------------------ */ + +_Static_assert(CHAR_BIT >= 8, "C11 5.2.4.2.1"); +_Static_assert(SCHAR_MIN <= -127, "C11 5.2.4.2.1"); +_Static_assert(SCHAR_MAX >= 127, "C11 5.2.4.2.1"); +_Static_assert(UCHAR_MAX >= 255, "C11 5.2.4.2.1"); +_Static_assert(SHRT_MIN <= -32767, "C11 5.2.4.2.1"); +_Static_assert(SHRT_MAX >= 32767, "C11 5.2.4.2.1"); +_Static_assert(INT_MIN <= -32767, "C11 5.2.4.2.1"); +_Static_assert(INT_MAX >= 32767, "C11 5.2.4.2.1"); +_Static_assert(LONG_MAX >= 2147483647L, "C11 5.2.4.2.1"); +_Static_assert(LLONG_MAX >= 9223372036854775807LL,"C11 5.2.4.2.1"); +_Static_assert(MB_LEN_MAX >= 1, "C11 5.2.4.2.1"); + +_Static_assert(sizeof(int8_t) == 1, "exact width"); +_Static_assert(sizeof(int16_t) == 2, "exact width"); +_Static_assert(sizeof(int32_t) == 4, "exact width"); +_Static_assert(sizeof(int64_t) == 8, "exact width"); +_Static_assert(sizeof(uint8_t) == 1, "exact width"); +_Static_assert(sizeof(uint16_t) == 2, "exact width"); +_Static_assert(sizeof(uint32_t) == 4, "exact width"); +_Static_assert(sizeof(uint64_t) == 8, "exact width"); + +_Static_assert(INT8_MAX == 127, "limits 7.20.2"); +_Static_assert(INT8_MIN == -128, "limits 7.20.2"); +_Static_assert(UINT8_MAX == 255, "limits 7.20.2"); +_Static_assert(INT64_MAX == 9223372036854775807LL,"limits 7.20.2"); +_Static_assert(UINT64_MAX == 18446744073709551615ULL,"limits 7.20.2"); + +_Static_assert(sizeof(intptr_t) == sizeof(void *), "intptr_t holds void*"); +_Static_assert(sizeof(uintptr_t) == sizeof(void *), "uintptr_t holds void*"); +_Static_assert(sizeof(intmax_t) >= sizeof(long long), "intmax >= long long"); + +_Static_assert(INT32_C(1) + INT32_C(2) == 3, "INT_C macros work"); +_Static_assert(UINT64_C(0xFFFFFFFFFFFFFFFF) == UINT64_MAX, "UINT64_C"); + +/* iso646 substitutions */ +_Static_assert((1 and 1) == 1, "and"); +_Static_assert((1 or 0) == 1, "or"); +_Static_assert((compl 0) == -1, "compl"); +_Static_assert((1 xor 1) == 0, "xor"); + +/* stdbool */ +_Static_assert(sizeof(bool) >= 1, "bool exists"); +_Static_assert(true == 1, "true"); +_Static_assert(false == 0, "false"); +_Static_assert(__bool_true_false_are_defined == 1, "marker macro"); + +/* stdalign */ +_Static_assert(__alignof_is_defined == 1, "alignof marker"); +_Static_assert(__alignas_is_defined == 1, "alignas marker"); +_Static_assert(alignof(int) >= 1, "alignof works"); +alignas(16) static char aligned_buf[16]; +_Static_assert(alignof(max_align_t) >= alignof(long double), "max_align_t"); + +/* stddef */ +_Static_assert(sizeof(size_t) == sizeof(sizeof(int)), "size_t"); +_Static_assert(sizeof(ptrdiff_t) == sizeof((int *)0 - (int *)0), "ptrdiff_t"); + +struct s_off { char a; int b; }; +_Static_assert(offsetof(struct s_off, b) > 0, "offsetof"); + +/* float.h: a few of the C11 minimums (5.2.4.2.2). */ +_Static_assert(FLT_RADIX >= 2, "5.2.4.2.2"); +_Static_assert(FLT_MANT_DIG >= 6, "5.2.4.2.2"); +_Static_assert(DBL_MANT_DIG >= FLT_MANT_DIG, "double >= float precision"); +_Static_assert(LDBL_MANT_DIG >= DBL_MANT_DIG, "long double >= double"); +_Static_assert(DECIMAL_DIG >= 10, "5.2.4.2.2"); + +/* stdarg: must be usable in a vararg function. */ +static int sum_n(int n, ...) { + va_list ap; + va_start(ap, n); + int s = 0; + for (int i = 0; i < n; ++i) s += va_arg(ap, int); + va_end(ap); + return s; +} + +/* stdnoreturn: macro must expand to a usable function specifier. */ +static noreturn void cfree_trap(void) { for (;;) {} } + +/* Reference everything so -Wunused-* stays quiet. */ +int cfree_smoke_ok(void) { + (void)aligned_buf; + if (0) cfree_trap(); + return sum_n(3, 1, 2, 3) == 6; +}