Skip to content

Conversation

@alejandro-colomar
Copy link
Collaborator

@alejandro-colomar alejandro-colomar commented Nov 15, 2025

Cc: @uecker , @thradams


Revisions:

v2
  • Reorder commits.
  • Improve comment.
interdiff
$ git diff gh/T..T
diff --git a/lib/alloc/realloc.h b/lib/alloc/realloc.h
index 97e9b1fde..577d086c0 100644
--- a/lib/alloc/realloc.h
+++ b/lib/alloc/realloc.h
@@ -14,12 +14,12 @@
 #include "sizeof.h"
 
 
-#define reallocarray_(p, n, size)  reallocarray(p, (n) ?: 1, (size) ?: 1)
-
 // realloc_T - realloc type-safe
 #define realloc_T(p, n, T)   realloc_T_(p, n, typeas(T))
 #define realloc_T_(p, n, T)  ((T *){reallocarray_((T *){p}, n, sizeof(T))})
 
+#define reallocarray_(p, n, size)  reallocarray(p, (n) ?: 1, (size) ?: 1)
+
 
 // xrealloc_T - exit-on-error realloc type-safe
 #define xrealloc_T(p, n, T)  exit_if_null(realloc_T(p, n, T))
diff --git a/lib/alloc/reallocf.h b/lib/alloc/reallocf.h
index d6527f830..3a40f6365 100644
--- a/lib/alloc/reallocf.h
+++ b/lib/alloc/reallocf.h
@@ -15,12 +15,12 @@
 #include "sizeof.h"
 
 
-#define reallocarrayf_(p, n, size)  reallocarrayf(p, (n) ?: 1, (size) ?: 1)
-
 // reallocf_T - realloc free-on-error type-safe
 #define reallocf_T(p, n, T)   reallocf_T_(p, n, typeas(T))
 #define reallocf_T_(p, n, T)  ((T *){reallocarrayf_((T *){p}, n, sizeof(T))})
 
+#define reallocarrayf_(p, n, size)  reallocarrayf(p, (n) ?: 1, (size) ?: 1)
+
 
 // reallocarrayf - realloc array free-on-error
 ATTR_ALLOC_SIZE(2, 3)
diff --git a/lib/search/l/lsearch.h b/lib/search/l/lsearch.h
index 3aabc54bc..5b477d472 100644
--- a/lib/search/l/lsearch.h
+++ b/lib/search/l/lsearch.h
@@ -14,7 +14,7 @@
 #include "sizeof.h"
 
 
-// lsearch_T - linear search type-safe
+// lsearch_T - linear search-and-insert type-safe
 #define lsearch_T(T, k, a, n, cmp)   lsearch_T_(typeas(T), k, a, n, cmp)
 #define lsearch_T_(T, k, a, n, cmp)                                   \
 (                                                                     \
range-diff
$ git rd --creation-factor=99 -U0
 1:  62ab264e5 =  1:  62ab264e5 lib/: Use a consistent name for macro arguments representing a type name
 2:  85b5ea42c =  2:  85b5ea42c lib/: Use compound literals to avoid casts
 3:  d93c426d8 =  3:  d93c426d8 lib/search/, lib/, src/: Add a type parameter to the type-safe macros
 5:  2bb11a414 =  4:  7f341b6e9 lib/search/: Simplify CMP()
 4:  c08d722c7 =  5:  3f0de5556 lib/sizeof.h: typeas(): Add macro
 7:  7f446588d !  6:  830578bf3 lib/search/: Use compound literals to avoid local variables
    @@ lib/search/l/lfind.h
    --  const typeas(T)  *k_ = k;                                     \
    --  const typeas(T)  *a_ = a;                                     \
    +-  const T  *k_ = k;                                             \
    +-  const T  *a_ = a;                                             \
    @@ lib/search/l/lfind.h
    --  (typeas(T) *){lfind_(k_, a_, n, sizeof(T), CMP(T))};          \
    +-  (T *){lfind_(k_, a_, n, sizeof(T), CMP(T))};                  \
    @@ lib/search/l/lfind.h
    -+  (typeas(T) *){                                                \
    -+          lfind_(                                               \
    -+                  (const typeas(T) *){k},                       \
    -+                  (const typeas(T) *){a},                       \
    -+                  n,                                            \
    -+                  sizeof(T),                                    \
    -+                  CMP(T)                                        \
    -+          )                                                     \
    -+  }                                                             \
    ++  (T *){lfind_((const T *){k}, (const T *){a}, n, sizeof(T), CMP(T))}\
    @@ lib/search/l/lsearch.h
    --  const typeas(T)  *k_ = k;                                     \
    --  typeas(T)        *a_ = a;                                     \
    +-  const T  *k_ = k;                                             \
    +-  T        *a_ = a;                                             \
    @@ lib/search/l/lsearch.h
    --  (typeas(T) *){lsearch(k_, a_, n, sizeof(T), CMP(T))};         \
    +-  (T *){lsearch(k_, a_, n, sizeof(T), CMP(T))};                 \
    @@ lib/search/l/lsearch.h
    -+  (typeas(T) *){                                                \
    -+          lsearch(                                              \
    -+                  (const typeas(T) *){k},                       \
    -+                  (typeas(T) *){a},                             \
    -+                  n,                                            \
    -+                  sizeof(T),                                    \
    -+                  CMP(T)                                        \
    -+          )                                                     \
    -+  }                                                             \
    ++  (T *){lsearch((const T *){k}, (T *){a}, n, sizeof(T), CMP(T))}\
    @@ lib/search/sort/qsort.h
    + #include "search/cmp/cmp.h"
    @@ lib/search/sort/qsort.h
    - #define QSORT(T, a, n)  do                                            \
    - {                                                                     \
    --  typeas(T)  *p_ = a;                                           \
    + 
    +-#define QSORT(T, a, n)  do                                            \
    +-{                                                                     \
    +-  T  *p_ = a;                                                   \
    @@ lib/search/sort/qsort.h
    -+  qsort((typeas(T) *){a}, n, sizeof(T), CMP(T));                \
    - } while (0)
    +-} while (0)
    ++#define QSORT(T, a, n)  qsort((T *){a}, n, sizeof(T), CMP(T))
    @@ lib/search/sort/qsort.h
    + #endif  // include guard
 6:  16f3a9d39 !  7:  9fc8d530e lib/{alloc,search}/: Use typeas() to add support for arbitrary types
    @@ lib/alloc/calloc.h
    - #define CALLOC(n, T)                                                  \
    - (                                                                     \
    +-#define CALLOC(n, T)                                                  \
    +-(                                                                     \
    @@ lib/alloc/calloc.h
    -+  (typeas(T) *){calloc(n, sizeof(T))}                           \
    - )
    +-)
    ++#define CALLOC(n, T)   CALLOC_(n, typeas(T))
    ++#define CALLOC_(n, T)  ((T *){calloc(n, sizeof(T))})
    @@ lib/alloc/calloc.h
    + #define XCALLOC(n, T)  exit_if_null(CALLOC(n, T))
    @@ lib/alloc/malloc.h
    - #define MALLOC(n, T)                                                  \
    - (                                                                     \
    +-#define MALLOC(n, T)                                                  \
    +-(                                                                     \
    @@ lib/alloc/malloc.h
    -+  (typeas(T) *){mallocarray(n, sizeof(T))}                      \
    - )
    +-)
    ++#define MALLOC(n, T)   MALLOC_(n, typeas(T))
    ++#define MALLOC_(n, T)  ((T *){mallocarray(n, sizeof(T))})
    @@ lib/alloc/malloc.h
    + #define XMALLOC(n, T)  exit_if_null(MALLOC(n, T))
    @@ lib/alloc/realloc.h
    - #define REALLOC(p, n, T)                                              \
    +-#define REALLOC(p, n, T)                                              \
    ++#define REALLOC(p, n, T)   REALLOC_(p, n, typeas(T))
    ++#define REALLOC_(p, n, T)                                             \
    @@ lib/alloc/realloc.h
    --  _Generic(p, T *: (T *){reallocarray(p, (n) ?: 1, sizeof(T))}) \
    -+  _Generic(p, typeas(T) *:                                      \
    -+          (typeas(T) *){reallocarray(p, (n) ?: 1, sizeof(T))}   \
    -+  )                                                             \
    +   _Generic(p, T *: (T *){reallocarray(p, (n) ?: 1, sizeof(T))}) \
    @@ lib/alloc/realloc.h
    - 
    - 
    @@ lib/alloc/reallocf.h
    - #define REALLOCF(p, n, T)                                             \
    +-#define REALLOCF(p, n, T)                                             \
    ++#define REALLOCF(p, n, T)   REALLOCF_(p, n, typeas(T))
    ++#define REALLOCF_(p, n, T)                                            \
    @@ lib/alloc/reallocf.h
    --  _Generic(p, T *: (T *){reallocarrayf(p, (n) ?: 1, sizeof(T))}) \
    -+  _Generic(p, typeas(T) *:                                      \
    -+          (typeas(T) *){reallocarrayf(p, (n) ?: 1, sizeof(T))}  \
    -+  )                                                             \
    +   _Generic(p, T *: (T *){reallocarrayf(p, (n) ?: 1, sizeof(T))}) \
    @@ lib/alloc/reallocf.h
    - 
    - 
    @@ lib/search/l/lfind.h
    - #define LFIND(T, k, a, n)                                             \
    - ({                                                                    \
    --  const T  *k_ = k;                                             \
    --  const T  *a_ = a;                                             \
    -+  const typeas(T)  *k_ = k;                                     \
    -+  const typeas(T)  *a_ = a;                                     \
    -                                                                       \
    --  (T *){lfind_(k_, a_, n, sizeof(T), CMP(T))};                  \
    -+  (typeas(T) *){lfind_(k_, a_, n, sizeof(T), CMP(T))};          \
    - })
    - 
    - 
    +-#define LFIND(T, k, a, n)                                             \
    ++#define LFIND(T, k, a, n)   LFIND_(typeas(T), k, a, n)
    ++#define LFIND_(T, k, a, n)                                            \
    + (                                                                     \
    +   (T *){lfind_((const T *){k}, (const T *){a}, n, sizeof(T), CMP(T))}\
    + )
    @@ lib/search/l/lsearch.h
    - #define LSEARCH(T, k, a, n)                                           \
    - ({                                                                    \
    --  const T  *k_ = k;                                             \
    --  T        *a_ = a;                                             \
    -+  const typeas(T)  *k_ = k;                                     \
    -+  typeas(T)        *a_ = a;                                     \
    -                                                                       \
    --  (T *){lsearch(k_, a_, n, sizeof(T), CMP(T))};                 \
    -+  (typeas(T) *){lsearch(k_, a_, n, sizeof(T), CMP(T))};         \
    - })
    - 
    - 
    +-#define LSEARCH(T, k, a, n)                                           \
    ++#define LSEARCH(T, k, a, n)   LSEARCH_(typeas(T), k, a, n)
    ++#define LSEARCH_(T, k, a, n)                                          \
    + (                                                                     \
    +   (T *){lsearch((const T *){k}, (T *){a}, n, sizeof(T), CMP(T))}\
    + )
    @@ lib/search/sort/qsort.h
    - #define QSORT(T, a, n)  do                                            \
    - {                                                                     \
    --  T  *p_ = a;                                                   \
    -+  typeas(T)  *p_ = a;                                           \
    -                                                                       \
    -   qsort(p_, n, sizeof(T), CMP(T));                              \
    - } while (0)
    +-#define QSORT(T, a, n)  qsort((T *){a}, n, sizeof(T), CMP(T))
    ++#define QSORT(T, a, n)   QSORT_(typeas(T), a, n)
    ++#define QSORT_(T, a, n)  qsort((T *){a}, n, sizeof(T), CMP(T))
    + 
    + 
    + #endif  // include guard
 8:  c211e51a9 !  8:  913fe2691 lib/alloc/: REALLOC[F](): Use compound literal to avoid _Generic(3)
    @@ Commit message
    -    lib/alloc/: REALLOC[F](): Use compound literal to avoid _Generic(3)
    -
    -    Compound literals are much more portable (standardized in ISO C99) than
    -    _Generic(3) (standardized in ISO C11).
    -
    -    Compound literals have a small difference: they accept a void* as input.
    -    This makes these APIs slightly less strict.  However, that shouldn't be
    -    a big problem: most APIs in C accept void*, and having one that doesn't
    -    accept them wouldn't be a significant safety measure.
    -
    -    On the other hand, this makes these macros more useful to arbitrary
    -    programmers, as they would rightfully expect void* to be valid input to
    -    any API.
    -
    -    Instead, the focus should be in reducing void* variables.  We do indeed
    -    use very few of those.  And I'll work in removing more of those.
    +    lib/alloc/: reallocarray[f]_(): Add helper macros to handle n?:1
    @@ lib/alloc/realloc.h
    - 
    - #define REALLOC(p, n, T)                                              \
    + #define REALLOC(p, n, T)   REALLOC_(p, n, typeas(T))
    + #define REALLOC_(p, n, T)                                             \
    @@ lib/alloc/realloc.h
    --  _Generic(p, typeas(T) *:                                      \
    --          (typeas(T) *){reallocarray(p, (n) ?: 1, sizeof(T))}   \
    --  )                                                             \
    -+  (typeas(T) *){reallocarray((typeas(T) *){p}, (n) ?: 1, sizeof(T))}\
    +-  _Generic(p, T *: (T *){reallocarray(p, (n) ?: 1, sizeof(T))}) \
    ++  _Generic(p, T *: (T *){reallocarray_(p, n, sizeof(T))})       \
    @@ lib/alloc/realloc.h
    ++#define reallocarray_(p, n, size)  reallocarray(p, (n) ?: 1, (size) ?: 1)
    ++
    + 
    + #define XREALLOC(p, n, T)  exit_if_null(REALLOC(p, n, T))
    @@ lib/alloc/reallocf.h
    - 
    - #define REALLOCF(p, n, T)                                             \
    + #define REALLOCF(p, n, T)   REALLOCF_(p, n, typeas(T))
    + #define REALLOCF_(p, n, T)                                            \
    @@ lib/alloc/reallocf.h
    --  _Generic(p, typeas(T) *:                                      \
    --          (typeas(T) *){reallocarrayf(p, (n) ?: 1, sizeof(T))}  \
    --  )                                                             \
    -+  (typeas(T) *){reallocarrayf((typeas(T) *){p}, (n) ?: 1, sizeof(T))}\
    +-  _Generic(p, T *: (T *){reallocarrayf(p, (n) ?: 1, sizeof(T))}) \
    ++  _Generic(p, T *: (T *){reallocarrayf_(p, n, sizeof(T))})      \
    @@ lib/alloc/reallocf.h
    ++#define reallocarrayf_(p, n, size)  reallocarrayf(p, (n) ?: 1, (size) ?: 1)
    ++
    @@ lib/alloc/reallocf.h
    + ATTR_ALLOC_SIZE(2, 3)
    + ATTR_MALLOC(free)
 9:  80bcf9e90 !  9:  fa1ed01c7 lib/alloc/: reallocarray[f]_(): Add helper macros to handle n?:1
    @@ Commit message
    -    lib/alloc/: reallocarray[f]_(): Add helper macros to handle n?:1
    +    lib/alloc/: REALLOC[F](): Use compound literal to avoid _Generic(3)
    +
    +    Compound literals are much more portable (standardized in ISO C99) than
    +    _Generic(3) (standardized in ISO C11).
    +
    +    Compound literals have a small difference: they accept a void* as input.
    +    This makes these APIs slightly less strict.  However, that shouldn't be
    +    a big problem: most APIs in C accept void*, and having one that doesn't
    +    accept them wouldn't be a significant safety measure.
    +
    +    On the other hand, this makes these macros more useful to arbitrary
    +    programmers, as they would rightfully expect void* to be valid input to
    +    any API.
    +
    +    Instead, the focus should be in reducing void* variables.  We do indeed
    +    use very few of those.  And I'll work in removing more of those.
    @@ lib/alloc/realloc.h
    - #include "sizeof.h"
    @@ lib/alloc/realloc.h
    -+#define reallocarray_(p, n, size)  reallocarray(p, (n) ?: 1, (size) ?: 1)
    - #define REALLOC(p, n, T)                                              \
    - (                                                                     \
    --  (typeas(T) *){reallocarray((typeas(T) *){p}, (n) ?: 1, sizeof(T))}\
    -+  (typeas(T) *){reallocarray_((typeas(T) *){p}, n, sizeof(T))}  \
    - )
    + #define REALLOC(p, n, T)   REALLOC_(p, n, typeas(T))
    +-#define REALLOC_(p, n, T)                                             \
    +-(                                                                     \
    +-  _Generic(p, T *: (T *){reallocarray_(p, n, sizeof(T))})       \
    +-)
    ++#define REALLOC_(p, n, T)  ((T *){reallocarray_((T *){p}, n, sizeof(T))})
    @@ lib/alloc/realloc.h
    + #define reallocarray_(p, n, size)  reallocarray(p, (n) ?: 1, (size) ?: 1)
    @@ lib/alloc/reallocf.h
    - #include "sizeof.h"
    @@ lib/alloc/reallocf.h
    -+#define reallocarrayf_(p, n, size)  reallocarrayf(p, (n) ?: 1, (size) ?: 1)
    - #define REALLOCF(p, n, T)                                             \
    - (                                                                     \
    --  (typeas(T) *){reallocarrayf((typeas(T) *){p}, (n) ?: 1, sizeof(T))}\
    -+  (typeas(T) *){reallocarrayf_((typeas(T) *){p}, n, sizeof(T))} \
    - )
    + #define REALLOCF(p, n, T)   REALLOCF_(p, n, typeas(T))
    +-#define REALLOCF_(p, n, T)                                            \
    +-(                                                                     \
    +-  _Generic(p, T *: (T *){reallocarrayf_(p, n, sizeof(T))})      \
    +-)
    ++#define REALLOCF_(p, n, T)  ((T *){reallocarrayf_((T *){p}, n, sizeof(T))})
    @@ lib/alloc/reallocf.h
    + #define reallocarrayf_(p, n, size)  reallocarrayf(p, (n) ?: 1, (size) ?: 1)
10:  6f778e6ce ! 10:  2f2391ccf lib/search/: Split APIs
    @@ lib/search/l/lfind.h
    --#define LFIND(T, k, a, n)                                             \
    +-#define LFIND(T, k, a, n)   LFIND_(typeas(T), k, a, n)
    +-#define LFIND_(T, k, a, n)                                            \
    @@ lib/search/l/lfind.h
    -+#define lfind_T(T, k, a, n, cmp)                                      \
    ++#define lfind_T(T, k, a, n, cmp)   lfind_T_(typeas(T), k, a, n, cmp)
    ++#define lfind_T_(T, k, a, n, cmp)                                     \
    @@ lib/search/l/lfind.h
    -   (typeas(T) *){                                                \
    -           lfind_(                                               \
    -@@
    -                   (const typeas(T) *){a},                       \
    -                   n,                                            \
    -                   sizeof(T),                                    \
    --                  CMP(T)                                        \
    -+                  cmp                                           \
    -           )                                                     \
    -   }                                                             \
    +-  (T *){lfind_((const T *){k}, (const T *){a}, n, sizeof(T), CMP(T))}\
    ++  (T *){lfind_((const T *){k}, (const T *){a}, n, sizeof(T), cmp)}\
    @@ lib/search/l/lsearch.h
    --#define LSEARCH(T, k, a, n)                                           \
    -+// lsearch_T - linear search type-safe
    -+#define lsearch_T(T, k, a, n, cmp)                                    \
    +-#define LSEARCH(T, k, a, n)   LSEARCH_(typeas(T), k, a, n)
    +-#define LSEARCH_(T, k, a, n)                                          \
    ++// lsearch_T - linear search-and-insert type-safe
    ++#define lsearch_T(T, k, a, n, cmp)   lsearch_T_(typeas(T), k, a, n, cmp)
    ++#define lsearch_T_(T, k, a, n, cmp)                                   \
    @@ lib/search/l/lsearch.h
    -   (typeas(T) *){                                                \
    -           lsearch(                                              \
    -@@
    -                   (typeas(T) *){a},                             \
    -                   n,                                            \
    -                   sizeof(T),                                    \
    --                  CMP(T)                                        \
    -+                  cmp                                           \
    -           )                                                     \
    -   }                                                             \
    +-  (T *){lsearch((const T *){k}, (T *){a}, n, sizeof(T), CMP(T))}\
    ++  (T *){lsearch((const T *){k}, (T *){a}, n, sizeof(T), cmp)}   \
    @@ lib/search/sort/qsort.h
    --#define QSORT(T, a, n)  do                                            \
    +-#define QSORT(T, a, n)   QSORT_(typeas(T), a, n)
    +-#define QSORT_(T, a, n)  qsort((T *){a}, n, sizeof(T), CMP(T))
    @@ lib/search/sort/qsort.h
    -+#define qsort_T(T, a, n, cmp)  do                                     \
    - {                                                                     \
    --  qsort((typeas(T) *){a}, n, sizeof(T), CMP(T));                \
    -+  qsort((typeas(T) *){a}, n, sizeof(T), cmp);                   \
    - } while (0)
    - 
    -+#define QSORT(T, a, n)  qsort_T(T, a, n, CMP(T))
    ++#define qsort_T(T, a, n, cmp)   qsort_T_(typeas(T), a, n, cmp)
    ++#define qsort_T_(T, a, n, cmp)  qsort((T *){a}, n, sizeof(T), cmp)
    @@ lib/search/sort/qsort.h
    ++#define QSORT(T, a, n)  qsort_T(T, a, n, CMP(T))
    + 
11:  709b36f89 ! 11:  d2270ec53 lib/, src/: Rename REALLOCF() => reallocf_T()
    @@ lib/alloc/reallocf.h
    + #include "sizeof.h"
    @@ lib/alloc/reallocf.h
    +-#define REALLOCF(p, n, T)   REALLOCF_(p, n, typeas(T))
    +-#define REALLOCF_(p, n, T)  ((T *){reallocarrayf_((T *){p}, n, sizeof(T))})
    ++// reallocf_T - realloc free-on-error type-safe
    ++#define reallocf_T(p, n, T)   reallocf_T_(p, n, typeas(T))
    ++#define reallocf_T_(p, n, T)  ((T *){reallocarrayf_((T *){p}, n, sizeof(T))})
    + 
    @@ lib/alloc/reallocf.h
    --#define REALLOCF(p, n, T)                                             \
    -+
    -+// reallocf_T - realloc free-on-error type-safe
    -+#define reallocf_T(p, n, T)                                           \
    - (                                                                     \
    -   (typeas(T) *){reallocarrayf_((typeas(T) *){p}, n, sizeof(T))} \
    - )
12:  aadaffe47 ! 12:  46c45c29c lib/: Rename REALLOC() => realloc_T()
    @@ lib/alloc/realloc.h
    + #include "sizeof.h"
    @@ lib/alloc/realloc.h
    +-#define REALLOC(p, n, T)   REALLOC_(p, n, typeas(T))
    +-#define REALLOC_(p, n, T)  ((T *){reallocarray_((T *){p}, n, sizeof(T))})
    ++// realloc_T - realloc type-safe
    ++#define realloc_T(p, n, T)   realloc_T_(p, n, typeas(T))
    ++#define realloc_T_(p, n, T)  ((T *){reallocarray_((T *){p}, n, sizeof(T))})
    + 
    @@ lib/alloc/realloc.h
    --#define REALLOC(p, n, T)                                              \
    -+
    -+// realloc_T - realloc type-safe
    -+#define realloc_T(p, n, T)                                            \
    - (                                                                     \
    -   (typeas(T) *){reallocarray_((typeas(T) *){p}, n, sizeof(T))}  \
    - )
13:  8dd273db1 ! 13:  c777f5a70 lib/: Rename XREALLOC() => xrealloc_T()
    @@ lib/alloc/realloc.h
    - )
    + #define reallocarray_(p, n, size)  reallocarray(p, (n) ?: 1, (size) ?: 1)
14:  ec750344c ! 14:  2c84e4e43 lib/: Rename MALLOC() => malloc_T()
    @@ lib/alloc/malloc.h
    --#define MALLOC(n, T)                                                  \
    +-#define MALLOC(n, T)   MALLOC_(n, typeas(T))
    +-#define MALLOC_(n, T)  ((T *){mallocarray(n, sizeof(T))})
    @@ lib/alloc/malloc.h
    -+#define malloc_T(n, T)                                                  \
    - (                                                                     \
    -   (typeas(T) *){mallocarray(n, sizeof(T))}                      \
    - )
    ++#define malloc_T(n, T)   malloc_T_(n, typeas(T))
    ++#define malloc_T_(n, T)  ((T *){mallocarray(n, sizeof(T))})
15:  0784fae0e ! 15:  ec95fbe1c lib/: Rename XMALLOC() => xmalloc_T()
    @@ lib/alloc/malloc.h
    - )
    + #define malloc_T_(n, T)  ((T *){mallocarray(n, sizeof(T))})
16:  ee490b642 ! 16:  95cb2b82d lib/: Rename CALLOC() => calloc_T()
    @@ lib/alloc/calloc.h
    --#define CALLOC(n, T)                                                  \
    +-#define CALLOC(n, T)   CALLOC_(n, typeas(T))
    +-#define CALLOC_(n, T)  ((T *){calloc(n, sizeof(T))})
    @@ lib/alloc/calloc.h
    -+#define calloc_T(n, T)                                                \
    - (                                                                     \
    -   (typeas(T) *){calloc(n, sizeof(T))}                           \
    - )
    ++#define calloc_T(n, T)   calloc_T_(n, typeas(T))
    ++#define calloc_T_(n, T)  ((T *){calloc(n, sizeof(T))})
17:  4f865e6c3 ! 17:  c7ade821d lib/: Rename XCALLOC() => xcalloc_T()
    @@ lib/alloc/calloc.h
    - )
    + #define calloc_T_(n, T)  ((T *){calloc(n, sizeof(T))})
18:  8231d1c3d <  -:  --------- lib/{alloc,search}/: Use helper macros to reduce use of typeas()
v3
  • Remove return value to remove diagnostic.
$ git rd 
 1:  62ab264e5 =  1:  62ab264e5 lib/: Use a consistent name for macro arguments representing a type name
 2:  85b5ea42c =  2:  85b5ea42c lib/: Use compound literals to avoid casts
 3:  d93c426d8 =  3:  d93c426d8 lib/search/, lib/, src/: Add a type parameter to the type-safe macros
 4:  7f341b6e9 =  4:  7f341b6e9 lib/search/: Simplify CMP()
 5:  3f0de5556 =  5:  3f0de5556 lib/sizeof.h: typeas(): Add macro
 6:  830578bf3 =  6:  830578bf3 lib/search/: Use compound literals to avoid local variables
 7:  9fc8d530e =  7:  9fc8d530e lib/{alloc,search}/: Use typeas() to add support for arbitrary types
 8:  913fe2691 =  8:  913fe2691 lib/alloc/: reallocarray[f]_(): Add helper macros to handle n?:1
 9:  fa1ed01c7 =  9:  fa1ed01c7 lib/alloc/: REALLOC[F](): Use compound literal to avoid _Generic(3)
10:  2f2391ccf = 10:  2f2391ccf lib/search/: Split APIs
11:  d2270ec53 = 11:  d2270ec53 lib/, src/: Rename REALLOCF() => reallocf_T()
12:  46c45c29c = 12:  46c45c29c lib/: Rename REALLOC() => realloc_T()
13:  c777f5a70 = 13:  c777f5a70 lib/: Rename XREALLOC() => xrealloc_T()
14:  2c84e4e43 = 14:  2c84e4e43 lib/: Rename MALLOC() => malloc_T()
15:  ec95fbe1c = 15:  ec95fbe1c lib/: Rename XMALLOC() => xmalloc_T()
16:  95cb2b82d = 16:  95cb2b82d lib/: Rename CALLOC() => calloc_T()
17:  c7ade821d = 17:  c7ade821d lib/: Rename XCALLOC() => xcalloc_T()
 -:  --------- > 18:  593e6d341 lib/search/: lsearch_T(): Don't return anything
v4
  • Use variadic macros to avoid repetition.
$ git range-diff master 593e6d341 T -U0
 1:  62ab264e5 =  1:  62ab264e5 lib/: Use a consistent name for macro arguments representing a type name
 2:  85b5ea42c =  2:  85b5ea42c lib/: Use compound literals to avoid casts
 3:  d93c426d8 =  3:  d93c426d8 lib/search/, lib/, src/: Add a type parameter to the type-safe macros
 4:  7f341b6e9 =  4:  7f341b6e9 lib/search/: Simplify CMP()
 5:  3f0de5556 =  5:  3f0de5556 lib/sizeof.h: typeas(): Add macro
 6:  830578bf3 =  6:  830578bf3 lib/search/: Use compound literals to avoid local variables
 7:  9fc8d530e !  7:  878f874db lib/{alloc,search}/: Use typeas() to add support for arbitrary types
    @@ lib/search/l/lfind.h
    -+#define LFIND(T, k, a, n)   LFIND_(typeas(T), k, a, n)
    ++#define LFIND(T, ...)       LFIND_(typeas(T), __VA_ARGS__)
    @@ lib/search/l/lsearch.h
    -+#define LSEARCH(T, k, a, n)   LSEARCH_(typeas(T), k, a, n)
    ++#define LSEARCH(T, ...)       LSEARCH_(typeas(T), __VA_ARGS__)
    @@ lib/search/sort/qsort.h
    -+#define QSORT(T, a, n)   QSORT_(typeas(T), a, n)
    ++#define QSORT(T, ...)    QSORT_(typeas(T), __VA_ARGS__)
 8:  913fe2691 =  8:  357906311 lib/alloc/: reallocarray[f]_(): Add helper macros to handle n?:1
 9:  fa1ed01c7 =  9:  50ce5832a lib/alloc/: REALLOC[F](): Use compound literal to avoid _Generic(3)
10:  2f2391ccf ! 10:  b2b37ca83 lib/search/: Split APIs
    @@ lib/search/l/lfind.h
    --#define LFIND(T, k, a, n)   LFIND_(typeas(T), k, a, n)
    +-#define LFIND(T, ...)       LFIND_(typeas(T), __VA_ARGS__)
    @@ lib/search/l/lfind.h
    -+#define lfind_T(T, k, a, n, cmp)   lfind_T_(typeas(T), k, a, n, cmp)
    ++#define lfind_T(T, ...)            lfind_T_(typeas(T), __VA_ARGS__)
    @@ lib/search/l/lfind.h
    -+#define LFIND(T, k, a, n)  lfind_T(T, k, a, n, CMP(T))
    ++#define LFIND(T, ...)  lfind_T(T, __VA_ARGS__, CMP(T))
    @@ lib/search/l/lsearch.h
    --#define LSEARCH(T, k, a, n)   LSEARCH_(typeas(T), k, a, n)
    +-#define LSEARCH(T, ...)       LSEARCH_(typeas(T), __VA_ARGS__)
    @@ lib/search/l/lsearch.h
    -+#define lsearch_T(T, k, a, n, cmp)   lsearch_T_(typeas(T), k, a, n, cmp)
    ++#define lsearch_T(T, ...)            lsearch_T_(typeas(T), __VA_ARGS__)
    @@ lib/search/l/lsearch.h
    -+#define LSEARCH(T, k, a, n)  lsearch_T(T, k, a, n, CMP(T))
    ++#define LSEARCH(T, ...)  lsearch_T(T, __VA_ARGS__, CMP(T))
    @@ lib/search/sort/qsort.h
    --#define QSORT(T, a, n)   QSORT_(typeas(T), a, n)
    +-#define QSORT(T, ...)    QSORT_(typeas(T), __VA_ARGS__)
    @@ lib/search/sort/qsort.h
    -+#define qsort_T(T, a, n, cmp)   qsort_T_(typeas(T), a, n, cmp)
    ++#define qsort_T(T, ...)   qsort_T_(typeas(T), __VA_ARGS__)
    @@ lib/search/sort/qsort.h
    -+#define QSORT(T, a, n)  qsort_T(T, a, n, CMP(T))
    ++#define QSORT(T, ...)  qsort_T(T, __VA_ARGS__, CMP(T))
11:  d2270ec53 = 11:  796552d03 lib/, src/: Rename REALLOCF() => reallocf_T()
12:  46c45c29c = 12:  b2623f5bd lib/: Rename REALLOC() => realloc_T()
13:  c777f5a70 = 13:  3d25fd2e7 lib/: Rename XREALLOC() => xrealloc_T()
14:  2c84e4e43 = 14:  d13171c89 lib/: Rename MALLOC() => malloc_T()
15:  ec95fbe1c = 15:  5e1771ec0 lib/: Rename XMALLOC() => xmalloc_T()
16:  95cb2b82d = 16:  ce653684a lib/: Rename CALLOC() => calloc_T()
17:  c7ade821d = 17:  4ebfa2c3f lib/: Rename XCALLOC() => xcalloc_T()
18:  593e6d341 ! 18:  8810753a8 lib/search/: lsearch_T(): Don't return anything
    @@ lib/search/l/lsearch.h
    - #define lsearch_T(T, k, a, n, cmp)   lsearch_T_(typeas(T), k, a, n, cmp)
    + #define lsearch_T(T, ...)            lsearch_T_(typeas(T), __VA_ARGS__)
    @@ lib/search/l/lsearch.h
    - #define LSEARCH(T, k, a, n)  lsearch_T(T, k, a, n, CMP(T))
    + #define LSEARCH(T, ...)  lsearch_T(T, __VA_ARGS__, CMP(T))
v5
  • Keep some macros in multiple lines, instead of one line.
    I have plans for these macros for the future, and this will make it easier to apply those.
interdiff
$ git diff gh/T..T
diff --git a/lib/alloc/calloc.h b/lib/alloc/calloc.h
index b637fcf63..8013c1e35 100644
--- a/lib/alloc/calloc.h
+++ b/lib/alloc/calloc.h
@@ -16,7 +16,10 @@
 
 // calloc_T - calloc type-safe
 #define calloc_T(n, T)   calloc_T_(n, typeas(T))
-#define calloc_T_(n, T)  ((T *){calloc(n, sizeof(T))})
+#define calloc_T_(n, T)                                               \
+(                                                                     \
+       (T *){calloc(n, sizeof(T))}                                   \
+)
 
 
 // xcalloc_T - exit-on-error calloc type-safe
diff --git a/lib/alloc/malloc.h b/lib/alloc/malloc.h
index 9231062c5..95267f72b 100644
--- a/lib/alloc/malloc.h
+++ b/lib/alloc/malloc.h
@@ -17,7 +17,10 @@
 
 // malloc_T - malloc type-safe
 #define malloc_T(n, T)   malloc_T_(n, typeas(T))
-#define malloc_T_(n, T)  ((T *){mallocarray(n, sizeof(T))})
+#define malloc_T_(n, T)                                               \
+(                                                                     \
+       (T *){mallocarray(n, sizeof(T))}                              \
+)
 
 
 // xmalloc_T - exit-on-error malloc type-safe
diff --git a/lib/alloc/realloc.h b/lib/alloc/realloc.h
index 577d086c0..d449bddb4 100644
--- a/lib/alloc/realloc.h
+++ b/lib/alloc/realloc.h
@@ -16,7 +16,10 @@
 
 // realloc_T - realloc type-safe
 #define realloc_T(p, n, T)   realloc_T_(p, n, typeas(T))
-#define realloc_T_(p, n, T)  ((T *){reallocarray_((T *){p}, n, sizeof(T))})
+#define realloc_T_(p, n, T)                                           \
+(                                                                     \
+       (T *){reallocarray_((T *){p}, n, sizeof(T))}                  \
+)
 
 #define reallocarray_(p, n, size)  reallocarray(p, (n) ?: 1, (size) ?: 1)
 
diff --git a/lib/alloc/reallocf.h b/lib/alloc/reallocf.h
index 3a40f6365..51369715e 100644
--- a/lib/alloc/reallocf.h
+++ b/lib/alloc/reallocf.h
@@ -17,7 +17,10 @@
 
 // reallocf_T - realloc free-on-error type-safe
 #define reallocf_T(p, n, T)   reallocf_T_(p, n, typeas(T))
-#define reallocf_T_(p, n, T)  ((T *){reallocarrayf_((T *){p}, n, sizeof(T))})
+#define reallocf_T_(p, n, T)                                          \
+(                                                                     \
+       (T *){reallocarrayf_((T *){p}, n, sizeof(T))}                 \
+)
 
 #define reallocarrayf_(p, n, size)  reallocarrayf(p, (n) ?: 1, (size) ?: 1)
 
range-diff
$ git rd --creation-factor=99
 1:  62ab264e5 =  1:  62ab264e5 lib/: Use a consistent name for macro arguments representing a type name
 2:  85b5ea42c =  2:  85b5ea42c lib/: Use compound literals to avoid casts
 3:  d93c426d8 =  3:  d93c426d8 lib/search/, lib/, src/: Add a type parameter to the type-safe macros
 4:  7f341b6e9 =  4:  7f341b6e9 lib/search/: Simplify CMP()
 5:  3f0de5556 =  5:  3f0de5556 lib/sizeof.h: typeas(): Add macro
 6:  830578bf3 =  6:  830578bf3 lib/search/: Use compound literals to avoid local variables
 7:  878f874db !  7:  a486497a4 lib/{alloc,search}/: Use typeas() to add support for arbitrary types
    @@ lib/alloc/calloc.h
      
      
     -#define CALLOC(n, T)                                                  \
    --(                                                                     \
    --  (T *){calloc(n, sizeof(T))}                                   \
    --)
     +#define CALLOC(n, T)   CALLOC_(n, typeas(T))
    -+#define CALLOC_(n, T)  ((T *){calloc(n, sizeof(T))})
    - 
    - 
    - #define XCALLOC(n, T)  exit_if_null(CALLOC(n, T))
    ++#define CALLOC_(n, T)                                                 \
    + (                                                                     \
    +   (T *){calloc(n, sizeof(T))}                                   \
    + )
     
      ## lib/alloc/malloc.h ##
     @@
    @@ lib/alloc/malloc.h
      
      
     -#define MALLOC(n, T)                                                  \
    --(                                                                     \
    --  (T *){mallocarray(n, sizeof(T))}                              \
    --)
     +#define MALLOC(n, T)   MALLOC_(n, typeas(T))
    -+#define MALLOC_(n, T)  ((T *){mallocarray(n, sizeof(T))})
    - 
    - 
    - #define XMALLOC(n, T)  exit_if_null(MALLOC(n, T))
    ++#define MALLOC_(n, T)                                                 \
    + (                                                                     \
    +   (T *){mallocarray(n, sizeof(T))}                              \
    + )
     
      ## lib/alloc/realloc.h ##
     @@
 8:  357906311 =  8:  8bd235209 lib/alloc/: reallocarray[f]_(): Add helper macros to handle n?:1
 9:  50ce5832a !  9:  8999b2400 lib/alloc/: REALLOC[F](): Use compound literal to avoid _Generic(3)
    @@ Commit message
     
      ## lib/alloc/realloc.h ##
     @@
    - 
    - 
      #define REALLOC(p, n, T)   REALLOC_(p, n, typeas(T))
    --#define REALLOC_(p, n, T)                                             \
    --(                                                                     \
    + #define REALLOC_(p, n, T)                                             \
    + (                                                                     \
     -  _Generic(p, T *: (T *){reallocarray_(p, n, sizeof(T))})       \
    --)
    -+#define REALLOC_(p, n, T)  ((T *){reallocarray_((T *){p}, n, sizeof(T))})
    ++  (T *){reallocarray_((T *){p}, n, sizeof(T))}                  \
    + )
      
      #define reallocarray_(p, n, size)  reallocarray(p, (n) ?: 1, (size) ?: 1)
    - 
     
      ## lib/alloc/reallocf.h ##
     @@
    - 
    - 
      #define REALLOCF(p, n, T)   REALLOCF_(p, n, typeas(T))
    --#define REALLOCF_(p, n, T)                                            \
    --(                                                                     \
    + #define REALLOCF_(p, n, T)                                            \
    + (                                                                     \
     -  _Generic(p, T *: (T *){reallocarrayf_(p, n, sizeof(T))})      \
    --)
    -+#define REALLOCF_(p, n, T)  ((T *){reallocarrayf_((T *){p}, n, sizeof(T))})
    ++  (T *){reallocarrayf_((T *){p}, n, sizeof(T))}                 \
    + )
      
      #define reallocarrayf_(p, n, size)  reallocarrayf(p, (n) ?: 1, (size) ?: 1)
    - 
10:  b2b37ca83 = 10:  30c663e54 lib/search/: Split APIs
11:  796552d03 ! 11:  c6a468286 lib/, src/: Rename REALLOCF() => reallocf_T()
    @@ lib/alloc/reallocf.h
      
      
     -#define REALLOCF(p, n, T)   REALLOCF_(p, n, typeas(T))
    --#define REALLOCF_(p, n, T)  ((T *){reallocarrayf_((T *){p}, n, sizeof(T))})
    +-#define REALLOCF_(p, n, T)                                            \
     +// reallocf_T - realloc free-on-error type-safe
     +#define reallocf_T(p, n, T)   reallocf_T_(p, n, typeas(T))
    -+#define reallocf_T_(p, n, T)  ((T *){reallocarrayf_((T *){p}, n, sizeof(T))})
    - 
    ++#define reallocf_T_(p, n, T)                                          \
    + (                                                                     \
    +   (T *){reallocarrayf_((T *){p}, n, sizeof(T))}                 \
    + )
    +@@
      #define reallocarrayf_(p, n, size)  reallocarrayf(p, (n) ?: 1, (size) ?: 1)
      
      
12:  b2623f5bd ! 12:  5f65e0c6b lib/: Rename REALLOC() => realloc_T()
    @@ lib/alloc/realloc.h
      
      
     -#define REALLOC(p, n, T)   REALLOC_(p, n, typeas(T))
    --#define REALLOC_(p, n, T)  ((T *){reallocarray_((T *){p}, n, sizeof(T))})
    +-#define REALLOC_(p, n, T)                                             \
     +// realloc_T - realloc type-safe
     +#define realloc_T(p, n, T)   realloc_T_(p, n, typeas(T))
    -+#define realloc_T_(p, n, T)  ((T *){reallocarray_((T *){p}, n, sizeof(T))})
    - 
    ++#define realloc_T_(p, n, T)                                           \
    + (                                                                     \
    +   (T *){reallocarray_((T *){p}, n, sizeof(T))}                  \
    + )
    +@@
      #define reallocarray_(p, n, size)  reallocarray(p, (n) ?: 1, (size) ?: 1)
      
      
13:  3d25fd2e7 = 13:  90a02445b lib/: Rename XREALLOC() => xrealloc_T()
14:  d13171c89 ! 14:  aa1baaeb1 lib/: Rename MALLOC() => malloc_T()
    @@ lib/alloc/malloc.h
      
      
     -#define MALLOC(n, T)   MALLOC_(n, typeas(T))
    --#define MALLOC_(n, T)  ((T *){mallocarray(n, sizeof(T))})
    +-#define MALLOC_(n, T)                                                 \
     +// malloc_T - malloc type-safe
     +#define malloc_T(n, T)   malloc_T_(n, typeas(T))
    -+#define malloc_T_(n, T)  ((T *){mallocarray(n, sizeof(T))})
    ++#define malloc_T_(n, T)                                               \
    + (                                                                     \
    +   (T *){mallocarray(n, sizeof(T))}                              \
    + )
      
      
     -#define XMALLOC(n, T)  exit_if_null(MALLOC(n, T))
15:  5e1771ec0 ! 15:  e34e982df lib/: Rename XMALLOC() => xmalloc_T()
    @@ Commit message
     
      ## lib/alloc/malloc.h ##
     @@
    - #define malloc_T_(n, T)  ((T *){mallocarray(n, sizeof(T))})
    + )
      
      
     -#define XMALLOC(n, T)  exit_if_null(malloc_T(n, T))
16:  ce653684a ! 16:  147cf455f lib/: Rename CALLOC() => calloc_T()
    @@ lib/alloc/calloc.h
      
      
     -#define CALLOC(n, T)   CALLOC_(n, typeas(T))
    --#define CALLOC_(n, T)  ((T *){calloc(n, sizeof(T))})
    +-#define CALLOC_(n, T)                                                 \
     +// calloc_T - calloc type-safe
     +#define calloc_T(n, T)   calloc_T_(n, typeas(T))
    -+#define calloc_T_(n, T)  ((T *){calloc(n, sizeof(T))})
    ++#define calloc_T_(n, T)                                               \
    + (                                                                     \
    +   (T *){calloc(n, sizeof(T))}                                   \
    + )
      
      
     -#define XCALLOC(n, T)  exit_if_null(CALLOC(n, T))
17:  4ebfa2c3f ! 17:  ff77b777c lib/: Rename XCALLOC() => xcalloc_T()
    @@ Commit message
     
      ## lib/alloc/calloc.h ##
     @@
    - #define calloc_T_(n, T)  ((T *){calloc(n, sizeof(T))})
    + )
      
      
     -#define XCALLOC(n, T)  exit_if_null(calloc_T(n, T))
18:  8810753a8 = 18:  e6d4df2b0 lib/search/: lsearch_T(): Don't return anything
v5b
  • Rebase
$ git rd 
 1:  62ab264e5 =  1:  85b410574 lib/: Use a consistent name for macro arguments representing a type name
 2:  85b5ea42c =  2:  a77e2032e lib/: Use compound literals to avoid casts
 3:  d93c426d8 =  3:  4187e482b lib/search/, lib/, src/: Add a type parameter to the type-safe macros
 4:  7f341b6e9 =  4:  2efc2004b lib/search/: Simplify CMP()
 5:  3f0de5556 =  5:  10002cd09 lib/sizeof.h: typeas(): Add macro
 6:  830578bf3 =  6:  19ec5d5e6 lib/search/: Use compound literals to avoid local variables
 7:  a486497a4 =  7:  5a0277445 lib/{alloc,search}/: Use typeas() to add support for arbitrary types
 8:  8bd235209 =  8:  bccee1221 lib/alloc/: reallocarray[f]_(): Add helper macros to handle n?:1
 9:  8999b2400 =  9:  fc209dedc lib/alloc/: REALLOC[F](): Use compound literal to avoid _Generic(3)
10:  30c663e54 = 10:  463b9c569 lib/search/: Split APIs
11:  c6a468286 = 11:  196c55722 lib/, src/: Rename REALLOCF() => reallocf_T()
12:  5f65e0c6b = 12:  3cd34858a lib/: Rename REALLOC() => realloc_T()
13:  90a02445b = 13:  7b07af1a4 lib/: Rename XREALLOC() => xrealloc_T()
14:  aa1baaeb1 = 14:  3e1ae9c53 lib/: Rename MALLOC() => malloc_T()
15:  e34e982df = 15:  e0031a458 lib/: Rename XMALLOC() => xmalloc_T()
16:  147cf455f = 16:  903c7996a lib/: Rename CALLOC() => calloc_T()
17:  ff77b777c = 17:  a1f54bff5 lib/: Rename XCALLOC() => xcalloc_T()
18:  e6d4df2b0 = 18:  fc86ff709 lib/search/: lsearch_T(): Don't return anything
v6
  • Use register to not allow accidentally taking the address of compound literals.
$ git rd 
 1:  85b410574 =  1:  85b410574 lib/: Use a consistent name for macro arguments representing a type name
 2:  a77e2032e !  2:  a299e0a4e lib/: Use compound literals to avoid casts
    @@ Commit message
         don't have the unwanted effects on safety --casts disable most useful
         diagnostics--.
     
    +    Compound literals are lvalues, which means their address can be taken.
    +    To avoid this, we need to use the 'register' storage-class specifier.
    +
         Signed-off-by: Alejandro Colomar <[email protected]>
     
      ## lib/alloc/calloc.h ##
    @@ lib/alloc/calloc.h
      #define CALLOC(n, T)                                                  \
      (                                                                     \
     -  (T *) calloc(n, sizeof(T))                                    \
    -+  (T *){calloc(n, sizeof(T))}                                   \
    ++  (register T *){calloc(n, sizeof(T))}                          \
      )
      
      
    @@ lib/alloc/malloc.h
      #define MALLOC(n, T)                                                  \
      (                                                                     \
     -  (T *) mallocarray(n, sizeof(T))                               \
    -+  (T *){mallocarray(n, sizeof(T))}                              \
    ++  (register T *){mallocarray(n, sizeof(T))}                     \
      )
      
      
    @@ lib/alloc/realloc.h
      #define REALLOC(p, n, T)                                              \
      (                                                                     \
     -  _Generic(p, T *: (T *) reallocarray(p, (n) ?: 1, sizeof(T)))  \
    -+  _Generic(p, T *: (T *){reallocarray(p, (n) ?: 1, sizeof(T))}) \
    ++  _Generic(p, T *: (register T *){reallocarray(p, (n) ?: 1, sizeof(T))}) \
      )
      
      
    @@ lib/alloc/reallocf.h
      #define REALLOCF(p, n, T)                                             \
      (                                                                     \
     -  _Generic(p, T *: (T *) reallocarrayf(p, (n) ?: 1, sizeof(T))) \
    -+  _Generic(p, T *: (T *){reallocarrayf(p, (n) ?: 1, sizeof(T))}) \
    ++  _Generic(p, T *: (register T *){reallocarrayf(p, (n) ?: 1, sizeof(T))}) \
      )
      
      
    @@ lib/search/l/lfind.h
        static_assert(is_same_typeof(k_, a_), "");                    \
                                                                            \
     -  (typeof(k_)) lfind_(k_, a_, n, sizeof(*k_), CMP(typeof(k_))); \
    -+  (typeof(k_)){lfind_(k_, a_, n, sizeof(*k_), CMP(typeof(k_)))}; \
    ++  (register typeof(k_)){lfind_(k_, a_, n, sizeof(*k_), CMP(typeof(k_)))}; \
      })
      
      
    @@ lib/search/l/lsearch.h
        static_assert(is_same_typeof(k_, a_), "");                    \
                                                                            \
     -  (typeof(k_)) lsearch(k_, a_, n, sizeof(*k_), CMP(typeof(k_)));\
    -+  (typeof(k_)){lsearch(k_, a_, n, sizeof(*k_), CMP(typeof(k_)))};\
    ++  (register typeof(k_)){lsearch(k_, a_, n, sizeof(*k_), CMP(typeof(k_)))};\
      })
      
      
    @@ lib/sizeof.h
      
      
     -#define ssizeof(x)           ((ssize_t) sizeof(x))
    -+#define ssizeof(x)           ((ssize_t){sizeof(x)})
    ++#define ssizeof(x)           ((register ssize_t){sizeof(x)})
      #define memberof(T, member)  ((T){}.member)
      #define WIDTHOF(x)           (sizeof(x) * CHAR_BIT)
      
 3:  4187e482b !  3:  42d9c3695 lib/search/, lib/, src/: Add a type parameter to the type-safe macros
    @@ lib/search/l/lfind.h
                                                                            \
     -  static_assert(is_same_typeof(k_, a_), "");                    \
     -                                                                      \
    --  (typeof(k_)){lfind_(k_, a_, n, sizeof(*k_), CMP(typeof(k_)))}; \
    -+  (T *){lfind_(k_, a_, n, sizeof(T), CMP(T *))};                \
    +-  (register typeof(k_)){lfind_(k_, a_, n, sizeof(*k_), CMP(typeof(k_)))}; \
    ++  (register T *){lfind_(k_, a_, n, sizeof(T), CMP(T *))};       \
      })
      
      
    @@ lib/search/l/lsearch.h
                                                                            \
     -  static_assert(is_same_typeof(k_, a_), "");                    \
     -                                                                      \
    --  (typeof(k_)){lsearch(k_, a_, n, sizeof(*k_), CMP(typeof(k_)))};\
    -+  (T *){lsearch(k_, a_, n, sizeof(T), CMP(T *))};               \
    +-  (register typeof(k_)){lsearch(k_, a_, n, sizeof(*k_), CMP(typeof(k_)))};\
    ++  (register T *){lsearch(k_, a_, n, sizeof(T), CMP(T *))};      \
      })
      
      
 4:  2efc2004b !  4:  ef7b84bc5 lib/search/: Simplify CMP()
    @@ lib/search/l/lfind.h
        const T  *k_ = k;                                             \
        const T  *a_ = a;                                             \
                                                                            \
    --  (T *){lfind_(k_, a_, n, sizeof(T), CMP(T *))};                \
    -+  (T *){lfind_(k_, a_, n, sizeof(T), CMP(T))};                  \
    +-  (register T *){lfind_(k_, a_, n, sizeof(T), CMP(T *))};       \
    ++  (register T *){lfind_(k_, a_, n, sizeof(T), CMP(T))};         \
      })
      
      
    @@ lib/search/l/lsearch.h
        const T  *k_ = k;                                             \
        T        *a_ = a;                                             \
                                                                            \
    --  (T *){lsearch(k_, a_, n, sizeof(T), CMP(T *))};               \
    -+  (T *){lsearch(k_, a_, n, sizeof(T), CMP(T))};                 \
    +-  (register T *){lsearch(k_, a_, n, sizeof(T), CMP(T *))};      \
    ++  (register T *){lsearch(k_, a_, n, sizeof(T), CMP(T))};        \
      })
      
      
 5:  10002cd09 !  5:  2692904f2 lib/sizeof.h: typeas(): Add macro
    @@ lib/sizeof.h
      
     +#define typeas(T)            typeof((T){})
     +
    - #define ssizeof(x)           ((ssize_t){sizeof(x)})
    + #define ssizeof(x)           ((register ssize_t){sizeof(x)})
      #define memberof(T, member)  ((T){}.member)
      #define WIDTHOF(x)           (sizeof(x) * CHAR_BIT)
 6:  19ec5d5e6 !  6:  55c080504 lib/search/: Use compound literals to avoid local variables
    @@ Commit message
         This change also gets rid of some statement expressions, which are
         another non-standard feature.
     
    +    Compound literals are lvalues, which means their address can be taken.
    +    To avoid this, we need to use the 'register' storage-class specifier.
    +
         Signed-off-by: Alejandro Colomar <[email protected]>
     
      ## lib/search/l/lfind.h ##
    @@ lib/search/l/lfind.h
     -  const T  *k_ = k;                                             \
     -  const T  *a_ = a;                                             \
     -                                                                      \
    --  (T *){lfind_(k_, a_, n, sizeof(T), CMP(T))};                  \
    +-  (register T *){lfind_(k_, a_, n, sizeof(T), CMP(T))};         \
     -})
     +(                                                                     \
    -+  (T *){lfind_((const T *){k}, (const T *){a}, n, sizeof(T), CMP(T))}\
    ++  (register T *){                                               \
    ++          lfind_((register const T *){k}, (register const T *){a}, n, sizeof(T), CMP(T))\
    ++  }                                                             \
     +)
      
      
    @@ lib/search/l/lsearch.h
     -  const T  *k_ = k;                                             \
     -  T        *a_ = a;                                             \
     -                                                                      \
    --  (T *){lsearch(k_, a_, n, sizeof(T), CMP(T))};                 \
    +-  (register T *){lsearch(k_, a_, n, sizeof(T), CMP(T))};        \
     -})
     +(                                                                     \
    -+  (T *){lsearch((const T *){k}, (T *){a}, n, sizeof(T), CMP(T))}\
    ++  (register T *){                                               \
    ++          lsearch((register const T *){k}, (register T *){a}, n, sizeof(T), CMP(T))\
    ++  }                                                             \
     +)
      
      
    @@ lib/search/sort/qsort.h
     -                                                                      \
     -  qsort(p_, n, sizeof(T), CMP(T));                              \
     -} while (0)
    -+#define QSORT(T, a, n)  qsort((T *){a}, n, sizeof(T), CMP(T))
    ++#define QSORT(T, a, n)  qsort((register T *){a}, n, sizeof(T), CMP(T))
      
      
      #endif  // include guard
 7:  5a0277445 !  7:  4e1fc5336 lib/{alloc,search}/: Use typeas() to add support for arbitrary types
    @@ lib/alloc/calloc.h
     +#define CALLOC(n, T)   CALLOC_(n, typeas(T))
     +#define CALLOC_(n, T)                                                 \
      (                                                                     \
    -   (T *){calloc(n, sizeof(T))}                                   \
    +   (register T *){calloc(n, sizeof(T))}                          \
      )
     
      ## lib/alloc/malloc.h ##
    @@ lib/alloc/malloc.h
     +#define MALLOC(n, T)   MALLOC_(n, typeas(T))
     +#define MALLOC_(n, T)                                                 \
      (                                                                     \
    -   (T *){mallocarray(n, sizeof(T))}                              \
    +   (register T *){mallocarray(n, sizeof(T))}                     \
      )
     
      ## lib/alloc/realloc.h ##
    @@ lib/alloc/realloc.h
     +#define REALLOC(p, n, T)   REALLOC_(p, n, typeas(T))
     +#define REALLOC_(p, n, T)                                             \
      (                                                                     \
    -   _Generic(p, T *: (T *){reallocarray(p, (n) ?: 1, sizeof(T))}) \
    +   _Generic(p, T *: (register T *){reallocarray(p, (n) ?: 1, sizeof(T))}) \
      )
     
      ## lib/alloc/reallocf.h ##
    @@ lib/alloc/reallocf.h
     +#define REALLOCF(p, n, T)   REALLOCF_(p, n, typeas(T))
     +#define REALLOCF_(p, n, T)                                            \
      (                                                                     \
    -   _Generic(p, T *: (T *){reallocarrayf(p, (n) ?: 1, sizeof(T))}) \
    +   _Generic(p, T *: (register T *){reallocarrayf(p, (n) ?: 1, sizeof(T))}) \
      )
     
      ## lib/search/l/lfind.h ##
    @@ lib/search/l/lfind.h
     +#define LFIND(T, ...)       LFIND_(typeas(T), __VA_ARGS__)
     +#define LFIND_(T, k, a, n)                                            \
      (                                                                     \
    -   (T *){lfind_((const T *){k}, (const T *){a}, n, sizeof(T), CMP(T))}\
    - )
    +   (register T *){                                               \
    +           lfind_((register const T *){k}, (register const T *){a}, n, sizeof(T), CMP(T))\
     
      ## lib/search/l/lsearch.h ##
     @@
    @@ lib/search/l/lsearch.h
     +#define LSEARCH(T, ...)       LSEARCH_(typeas(T), __VA_ARGS__)
     +#define LSEARCH_(T, k, a, n)                                          \
      (                                                                     \
    -   (T *){lsearch((const T *){k}, (T *){a}, n, sizeof(T), CMP(T))}\
    - )
    +   (register T *){                                               \
    +           lsearch((register const T *){k}, (register T *){a}, n, sizeof(T), CMP(T))\
     
      ## lib/search/sort/qsort.h ##
     @@
    @@ lib/search/sort/qsort.h
     +#include "sizeof.h"
      
      
    --#define QSORT(T, a, n)  qsort((T *){a}, n, sizeof(T), CMP(T))
    +-#define QSORT(T, a, n)  qsort((register T *){a}, n, sizeof(T), CMP(T))
     +#define QSORT(T, ...)    QSORT_(typeas(T), __VA_ARGS__)
    -+#define QSORT_(T, a, n)  qsort((T *){a}, n, sizeof(T), CMP(T))
    ++#define QSORT_(T, a, n)  qsort((register T *){a}, n, sizeof(T), CMP(T))
      
      
      #endif  // include guard
 8:  bccee1221 !  8:  052a64b42 lib/alloc/: reallocarray[f]_(): Add helper macros to handle n?:1
    @@ lib/alloc/realloc.h
      #define REALLOC(p, n, T)   REALLOC_(p, n, typeas(T))
      #define REALLOC_(p, n, T)                                             \
      (                                                                     \
    --  _Generic(p, T *: (T *){reallocarray(p, (n) ?: 1, sizeof(T))}) \
    -+  _Generic(p, T *: (T *){reallocarray_(p, n, sizeof(T))})       \
    +-  _Generic(p, T *: (register T *){reallocarray(p, (n) ?: 1, sizeof(T))}) \
    ++  _Generic(p, T *: (register T *){reallocarray_(p, n, sizeof(T))}) \
      )
      
     +#define reallocarray_(p, n, size)  reallocarray(p, (n) ?: 1, (size) ?: 1)
    @@ lib/alloc/reallocf.h
      #define REALLOCF(p, n, T)   REALLOCF_(p, n, typeas(T))
      #define REALLOCF_(p, n, T)                                            \
      (                                                                     \
    --  _Generic(p, T *: (T *){reallocarrayf(p, (n) ?: 1, sizeof(T))}) \
    -+  _Generic(p, T *: (T *){reallocarrayf_(p, n, sizeof(T))})      \
    +-  _Generic(p, T *: (register T *){reallocarrayf(p, (n) ?: 1, sizeof(T))}) \
    ++  _Generic(p, T *: (register T *){reallocarrayf_(p, n, sizeof(T))}) \
      )
      
     +#define reallocarrayf_(p, n, size)  reallocarrayf(p, (n) ?: 1, (size) ?: 1)
 9:  fc209dedc !  9:  3b0e2ef01 lib/alloc/: REALLOC[F](): Use compound literal to avoid _Generic(3)
    @@ lib/alloc/realloc.h
      #define REALLOC(p, n, T)   REALLOC_(p, n, typeas(T))
      #define REALLOC_(p, n, T)                                             \
      (                                                                     \
    --  _Generic(p, T *: (T *){reallocarray_(p, n, sizeof(T))})       \
    -+  (T *){reallocarray_((T *){p}, n, sizeof(T))}                  \
    +-  _Generic(p, T *: (register T *){reallocarray_(p, n, sizeof(T))}) \
    ++  (register T *){reallocarray_((register T *){p}, n, sizeof(T))}\
      )
      
      #define reallocarray_(p, n, size)  reallocarray(p, (n) ?: 1, (size) ?: 1)
    @@ lib/alloc/reallocf.h
      #define REALLOCF(p, n, T)   REALLOCF_(p, n, typeas(T))
      #define REALLOCF_(p, n, T)                                            \
      (                                                                     \
    --  _Generic(p, T *: (T *){reallocarrayf_(p, n, sizeof(T))})      \
    -+  (T *){reallocarrayf_((T *){p}, n, sizeof(T))}                 \
    +-  _Generic(p, T *: (register T *){reallocarrayf_(p, n, sizeof(T))}) \
    ++  (register T *){reallocarrayf_((register T *){p}, n, sizeof(T))}\
      )
      
      #define reallocarrayf_(p, n, size)  reallocarrayf(p, (n) ?: 1, (size) ?: 1)
10:  463b9c569 ! 10:  7cff553b7 lib/search/: Split APIs
    @@ lib/search/l/lfind.h
     +#define lfind_T(T, ...)            lfind_T_(typeas(T), __VA_ARGS__)
     +#define lfind_T_(T, k, a, n, cmp)                                     \
      (                                                                     \
    --  (T *){lfind_((const T *){k}, (const T *){a}, n, sizeof(T), CMP(T))}\
    -+  (T *){lfind_((const T *){k}, (const T *){a}, n, sizeof(T), cmp)}\
    +   (register T *){                                               \
    +-          lfind_((register const T *){k}, (register const T *){a}, n, sizeof(T), CMP(T))\
    ++          lfind_((register const T *){k}, (register const T *){a}, n, sizeof(T), cmp)\
    +   }                                                             \
      )
      
     +#define LFIND(T, ...)  lfind_T(T, __VA_ARGS__, CMP(T))
    @@ lib/search/l/lsearch.h
     +#define lsearch_T(T, ...)            lsearch_T_(typeas(T), __VA_ARGS__)
     +#define lsearch_T_(T, k, a, n, cmp)                                   \
      (                                                                     \
    --  (T *){lsearch((const T *){k}, (T *){a}, n, sizeof(T), CMP(T))}\
    -+  (T *){lsearch((const T *){k}, (T *){a}, n, sizeof(T), cmp)}   \
    +   (register T *){                                               \
    +-          lsearch((register const T *){k}, (register T *){a}, n, sizeof(T), CMP(T))\
    ++          lsearch((register const T *){k}, (register T *){a}, n, sizeof(T), cmp)\
    +   }                                                             \
      )
      
     +#define LSEARCH(T, ...)  lsearch_T(T, __VA_ARGS__, CMP(T))
    @@ lib/search/sort/qsort.h
      
      
     -#define QSORT(T, ...)    QSORT_(typeas(T), __VA_ARGS__)
    --#define QSORT_(T, a, n)  qsort((T *){a}, n, sizeof(T), CMP(T))
    +-#define QSORT_(T, a, n)  qsort((register T *){a}, n, sizeof(T), CMP(T))
     +// qsort_T - sort type-safe
     +#define qsort_T(T, ...)   qsort_T_(typeas(T), __VA_ARGS__)
    -+#define qsort_T_(T, a, n, cmp)  qsort((T *){a}, n, sizeof(T), cmp)
    ++#define qsort_T_(T, a, n, cmp)  qsort((register T *){a}, n, sizeof(T), cmp)
     +
     +#define QSORT(T, ...)  qsort_T(T, __VA_ARGS__, CMP(T))
      
11:  196c55722 ! 11:  cd0b2711b lib/, src/: Rename REALLOCF() => reallocf_T()
    @@ lib/alloc/reallocf.h
     +#define reallocf_T(p, n, T)   reallocf_T_(p, n, typeas(T))
     +#define reallocf_T_(p, n, T)                                          \
      (                                                                     \
    -   (T *){reallocarrayf_((T *){p}, n, sizeof(T))}                 \
    +   (register T *){reallocarrayf_((register T *){p}, n, sizeof(T))}\
      )
     @@
      #define reallocarrayf_(p, n, size)  reallocarrayf(p, (n) ?: 1, (size) ?: 1)
12:  3cd34858a ! 12:  99755e67f lib/: Rename REALLOC() => realloc_T()
    @@ lib/alloc/realloc.h
     +#define realloc_T(p, n, T)   realloc_T_(p, n, typeas(T))
     +#define realloc_T_(p, n, T)                                           \
      (                                                                     \
    -   (T *){reallocarray_((T *){p}, n, sizeof(T))}                  \
    +   (register T *){reallocarray_((register T *){p}, n, sizeof(T))}\
      )
     @@
      #define reallocarray_(p, n, size)  reallocarray(p, (n) ?: 1, (size) ?: 1)
13:  7b07af1a4 = 13:  b6a3d6244 lib/: Rename XREALLOC() => xrealloc_T()
14:  3e1ae9c53 ! 14:  76fb271aa lib/: Rename MALLOC() => malloc_T()
    @@ lib/alloc/malloc.h
     +#define malloc_T(n, T)   malloc_T_(n, typeas(T))
     +#define malloc_T_(n, T)                                               \
      (                                                                     \
    -   (T *){mallocarray(n, sizeof(T))}                              \
    +   (register T *){mallocarray(n, sizeof(T))}                     \
      )
      
      
15:  e0031a458 = 15:  1ebc00006 lib/: Rename XMALLOC() => xmalloc_T()
16:  903c7996a ! 16:  28a963664 lib/: Rename CALLOC() => calloc_T()
    @@ lib/alloc/calloc.h
     +#define calloc_T(n, T)   calloc_T_(n, typeas(T))
     +#define calloc_T_(n, T)                                               \
      (                                                                     \
    -   (T *){calloc(n, sizeof(T))}                                   \
    +   (register T *){calloc(n, sizeof(T))}                          \
      )
      
      
17:  a1f54bff5 = 17:  8faece4a5 lib/: Rename XCALLOC() => xcalloc_T()
18:  fc86ff709 ! 18:  2ef110cc5 lib/search/: lsearch_T(): Don't return anything
    @@ lib/search/l/lsearch.h
      #define lsearch_T(T, ...)            lsearch_T_(typeas(T), __VA_ARGS__)
     -#define lsearch_T_(T, k, a, n, cmp)                                   \
     -(                                                                     \
    --  (T *){lsearch((const T *){k}, (T *){a}, n, sizeof(T), cmp)}   \
    +-  (register T *){                                               \
    +-          lsearch((register const T *){k}, (register T *){a}, n, sizeof(T), cmp)\
    +-  }                                                             \
     -)
     +#define lsearch_T_(T, k, a, n, cmp)  do                               \
     +{                                                                     \
    -+  lsearch((const T *){k}, (T *){a}, n, sizeof(T), cmp);         \
    ++  lsearch((register const T *){k}, (register T *){a}, n, sizeof(T), cmp);\
     +} while (0)
      
      #define LSEARCH(T, ...)  lsearch_T(T, __VA_ARGS__, CMP(T))
v7
  • Force lvalue conversion of compound literals with statement expressions. This is safer than register, which would also need const to prevent assignment. It's non-standard, but we're okay with that. If one would want write portable code, register const compound literals would be okay.
  • Use _Generic(3) to type-check arguments. This has stronger type safety properties. It also avoids having to do the register const thing to avoid lvalue issues, and results in more readable code, as each check can go in a separate line.
$ git rd --creation-factor=99
 1:  85b410574 =  1:  85b410574 lib/: Use a consistent name for macro arguments representing a type name
 2:  a299e0a4e !  2:  b0e13521e lib/: Use compound literals to avoid casts
    @@ Commit message
         don't have the unwanted effects on safety --casts disable most useful
         diagnostics--.
     
    -    Compound literals are lvalues, which means their address can be taken.
    -    To avoid this, we need to use the 'register' storage-class specifier.
    +    Compound literals are lvalues, which means their address can be taken,
    +    and they can also be assigned to.  To avoid this, we perform lvalue
    +    conversion through a statement expression.
     
         Signed-off-by: Alejandro Colomar <[email protected]>
     
      ## lib/alloc/calloc.h ##
     @@
      
    + 
      #define CALLOC(n, T)                                                  \
    - (                                                                     \
    +-(                                                                     \
     -  (T *) calloc(n, sizeof(T))                                    \
    -+  (register T *){calloc(n, sizeof(T))}                          \
    - )
    +-)
    ++({                                                                    \
    ++  (T *){calloc(n, sizeof(T))};                                  \
    ++})
      
      
    + #define XCALLOC(n, T)  exit_if_null(CALLOC(n, T))
     
      ## lib/alloc/malloc.h ##
     @@
      
    + 
      #define MALLOC(n, T)                                                  \
    - (                                                                     \
    +-(                                                                     \
     -  (T *) mallocarray(n, sizeof(T))                               \
    -+  (register T *){mallocarray(n, sizeof(T))}                     \
    - )
    +-)
    ++({                                                                    \
    ++  (T *){mallocarray(n, sizeof(T))};                             \
    ++})
      
      
    + #define XMALLOC(n, T)  exit_if_null(MALLOC(n, T))
     
      ## lib/alloc/realloc.h ##
     @@
      
    + 
      #define REALLOC(p, n, T)                                              \
    - (                                                                     \
    +-(                                                                     \
     -  _Generic(p, T *: (T *) reallocarray(p, (n) ?: 1, sizeof(T)))  \
    -+  _Generic(p, T *: (register T *){reallocarray(p, (n) ?: 1, sizeof(T))}) \
    - )
    +-)
    ++({                                                                    \
    ++  _Generic(p, T *: (T *){reallocarray(p, (n) ?: 1, sizeof(T))});\
    ++})
      
      
    + #define XREALLOC(p, n, T)  exit_if_null(REALLOC(p, n, T))
     
      ## lib/alloc/reallocf.h ##
     @@
      
    + 
      #define REALLOCF(p, n, T)                                             \
    - (                                                                     \
    +-(                                                                     \
     -  _Generic(p, T *: (T *) reallocarrayf(p, (n) ?: 1, sizeof(T))) \
    -+  _Generic(p, T *: (register T *){reallocarrayf(p, (n) ?: 1, sizeof(T))}) \
    - )
    +-)
    ++({                                                                    \
    ++  _Generic(p, T *: (T *){reallocarrayf(p, (n) ?: 1, sizeof(T))});\
    ++})
      
      
    + ATTR_ALLOC_SIZE(2, 3)
     
      ## lib/atoi/a2i/a2i.h ##
     @@
    @@ lib/search/l/lfind.h
        static_assert(is_same_typeof(k_, a_), "");                    \
                                                                            \
     -  (typeof(k_)) lfind_(k_, a_, n, sizeof(*k_), CMP(typeof(k_))); \
    -+  (register typeof(k_)){lfind_(k_, a_, n, sizeof(*k_), CMP(typeof(k_)))}; \
    ++  (typeof(k_)){lfind_(k_, a_, n, sizeof(*k_), CMP(typeof(k_)))};\
      })
      
      
    @@ lib/search/l/lsearch.h
        static_assert(is_same_typeof(k_, a_), "");                    \
                                                                            \
     -  (typeof(k_)) lsearch(k_, a_, n, sizeof(*k_), CMP(typeof(k_)));\
    -+  (register typeof(k_)){lsearch(k_, a_, n, sizeof(*k_), CMP(typeof(k_)))};\
    ++  (typeof(k_)){lsearch(k_, a_, n, sizeof(*k_), CMP(typeof(k_)))};\
      })
      
      
    @@ lib/sizeof.h
      
      
     -#define ssizeof(x)           ((ssize_t) sizeof(x))
    -+#define ssizeof(x)           ((register ssize_t){sizeof(x)})
    ++#define ssizeof(x)           ({(ssize_t){sizeof(x)};})
      #define memberof(T, member)  ((T){}.member)
      #define WIDTHOF(x)           (sizeof(x) * CHAR_BIT)
      
 3:  42d9c3695 !  3:  7150d4349 lib/search/, lib/, src/: Add a type parameter to the type-safe macros
    @@ lib/search/l/lfind.h
                                                                            \
     -  static_assert(is_same_typeof(k_, a_), "");                    \
     -                                                                      \
    --  (register typeof(k_)){lfind_(k_, a_, n, sizeof(*k_), CMP(typeof(k_)))}; \
    -+  (register T *){lfind_(k_, a_, n, sizeof(T), CMP(T *))};       \
    +-  (typeof(k_)){lfind_(k_, a_, n, sizeof(*k_), CMP(typeof(k_)))};\
    ++  (T *){lfind_(k_, a_, n, sizeof(T), CMP(T *))};                \
      })
      
      
    @@ lib/search/l/lsearch.h
                                                                            \
     -  static_assert(is_same_typeof(k_, a_), "");                    \
     -                                                                      \
    --  (register typeof(k_)){lsearch(k_, a_, n, sizeof(*k_), CMP(typeof(k_)))};\
    -+  (register T *){lsearch(k_, a_, n, sizeof(T), CMP(T *))};      \
    +-  (typeof(k_)){lsearch(k_, a_, n, sizeof(*k_), CMP(typeof(k_)))};\
    ++  (T *){lsearch(k_, a_, n, sizeof(T), CMP(T *))};               \
      })
      
      
 4:  ef7b84bc5 !  4:  9ed48c5d2 lib/search/: Simplify CMP()
    @@ lib/search/l/lfind.h
        const T  *k_ = k;                                             \
        const T  *a_ = a;                                             \
                                                                            \
    --  (register T *){lfind_(k_, a_, n, sizeof(T), CMP(T *))};       \
    -+  (register T *){lfind_(k_, a_, n, sizeof(T), CMP(T))};         \
    +-  (T *){lfind_(k_, a_, n, sizeof(T), CMP(T *))};                \
    ++  (T *){lfind_(k_, a_, n, sizeof(T), CMP(T))};                  \
      })
      
      
    @@ lib/search/l/lsearch.h
        const T  *k_ = k;                                             \
        T        *a_ = a;                                             \
                                                                            \
    --  (register T *){lsearch(k_, a_, n, sizeof(T), CMP(T *))};      \
    -+  (register T *){lsearch(k_, a_, n, sizeof(T), CMP(T))};        \
    +-  (T *){lsearch(k_, a_, n, sizeof(T), CMP(T *))};               \
    ++  (T *){lsearch(k_, a_, n, sizeof(T), CMP(T))};                 \
      })
      
      
 5:  2692904f2 !  5:  482f4a460 lib/sizeof.h: typeas(): Add macro
    @@ lib/sizeof.h
      
     +#define typeas(T)            typeof((T){})
     +
    - #define ssizeof(x)           ((register ssize_t){sizeof(x)})
    + #define ssizeof(x)           ({(ssize_t){sizeof(x)};})
      #define memberof(T, member)  ((T){}.member)
      #define WIDTHOF(x)           (sizeof(x) * CHAR_BIT)
 6:  55c080504 !  6:  a7733d2d1 lib/search/: Use compound literals to avoid local variables
    @@ Metadata
     Author: Alejandro Colomar <[email protected]>
     
      ## Commit message ##
    -    lib/search/: Use compound literals to avoid local variables
    +    lib/search/: Use _Generic(3) to avoid local variables
     
    -    Compound literals are a standard feature (ISO C99).
    -    They're safer than local variables in macros, which can cause issues
    -    when nesting such macros.
    -
    -    This change also gets rid of some statement expressions, which are
    -    another non-standard feature.
    -
    -    Compound literals are lvalues, which means their address can be taken.
    -    To avoid this, we need to use the 'register' storage-class specifier.
    +    Local variables in macros can cause issues when nesting such macros.
     
         Signed-off-by: Alejandro Colomar <[email protected]>
     
      ## lib/search/l/lfind.h ##
     @@
      
    - 
      #define LFIND(T, k, a, n)                                             \
    --({                                                                    \
    + ({                                                                    \
     -  const T  *k_ = k;                                             \
     -  const T  *a_ = a;                                             \
     -                                                                      \
    --  (register T *){lfind_(k_, a_, n, sizeof(T), CMP(T))};         \
    --})
    -+(                                                                     \
    -+  (register T *){                                               \
    -+          lfind_((register const T *){k}, (register const T *){a}, n, sizeof(T), CMP(T))\
    -+  }                                                             \
    -+)
    +-  (T *){lfind_(k_, a_, n, sizeof(T), CMP(T))};                  \
    ++  _Generic(k, T *: 0, const T *: 0);                            \
    ++  _Generic(a, T *: 0, const T *: 0);                            \
    ++  (T *){lfind_(k, a, n, sizeof(T), CMP(T))};                    \
    + })
      
      
    - inline void *lfind_(const void *k, const void *a, size_t n, size_t ksize,
     
      ## lib/search/l/lsearch.h ##
     @@
      
    - 
      #define LSEARCH(T, k, a, n)                                           \
    --({                                                                    \
    + ({                                                                    \
     -  const T  *k_ = k;                                             \
     -  T        *a_ = a;                                             \
     -                                                                      \
    --  (register T *){lsearch(k_, a_, n, sizeof(T), CMP(T))};        \
    --})
    -+(                                                                     \
    -+  (register T *){                                               \
    -+          lsearch((register const T *){k}, (register T *){a}, n, sizeof(T), CMP(T))\
    -+  }                                                             \
    -+)
    +-  (T *){lsearch(k_, a_, n, sizeof(T), CMP(T))};                 \
    ++  _Generic(k, T *: 0, const T *: 0);                            \
    ++  _Generic(a, T *: 0);                                          \
    ++  (T *){lsearch(k, a, n, sizeof(T), CMP(T))};                   \
    + })
      
      
    - #endif  // include guard
     
      ## lib/search/sort/qsort.h ##
     @@
    - #include "search/cmp/cmp.h"
      
    - 
    --#define QSORT(T, a, n)  do                                            \
    --{                                                                     \
    + #define QSORT(T, a, n)  do                                            \
    + {                                                                     \
     -  T  *p_ = a;                                                   \
     -                                                                      \
     -  qsort(p_, n, sizeof(T), CMP(T));                              \
    --} while (0)
    -+#define QSORT(T, a, n)  qsort((register T *){a}, n, sizeof(T), CMP(T))
    ++  _Generic(a, T *: 0);                                          \
    ++  qsort(a, n, sizeof(T), CMP(T));                               \
    + } while (0)
      
      
    - #endif  // include guard
 7:  4e1fc5336 !  7:  b79dda9d5 lib/{alloc,search}/: Use typeas() to add support for arbitrary types
    @@ lib/alloc/calloc.h
     -#define CALLOC(n, T)                                                  \
     +#define CALLOC(n, T)   CALLOC_(n, typeas(T))
     +#define CALLOC_(n, T)                                                 \
    - (                                                                     \
    -   (register T *){calloc(n, sizeof(T))}                          \
    - )
    + ({                                                                    \
    +   (T *){calloc(n, sizeof(T))};                                  \
    + })
     
      ## lib/alloc/malloc.h ##
     @@
    @@ lib/alloc/malloc.h
     -#define MALLOC(n, T)                                                  \
     +#define MALLOC(n, T)   MALLOC_(n, typeas(T))
     +#define MALLOC_(n, T)                                                 \
    - (                                                                     \
    -   (register T *){mallocarray(n, sizeof(T))}                     \
    - )
    + ({                                                                    \
    +   (T *){mallocarray(n, sizeof(T))};                             \
    + })
     
      ## lib/alloc/realloc.h ##
     @@
    @@ lib/alloc/realloc.h
     -#define REALLOC(p, n, T)                                              \
     +#define REALLOC(p, n, T)   REALLOC_(p, n, typeas(T))
     +#define REALLOC_(p, n, T)                                             \
    - (                                                                     \
    -   _Generic(p, T *: (register T *){reallocarray(p, (n) ?: 1, sizeof(T))}) \
    - )
    + ({                                                                    \
    +   _Generic(p, T *: (T *){reallocarray(p, (n) ?: 1, sizeof(T))});\
    + })
     
      ## lib/alloc/reallocf.h ##
     @@
    @@ lib/alloc/reallocf.h
     -#define REALLOCF(p, n, T)                                             \
     +#define REALLOCF(p, n, T)   REALLOCF_(p, n, typeas(T))
     +#define REALLOCF_(p, n, T)                                            \
    - (                                                                     \
    -   _Generic(p, T *: (register T *){reallocarrayf(p, (n) ?: 1, sizeof(T))}) \
    - )
    + ({                                                                    \
    +   _Generic(p, T *: (T *){reallocarrayf(p, (n) ?: 1, sizeof(T))});\
    + })
     
      ## lib/search/l/lfind.h ##
     @@
    @@ lib/search/l/lfind.h
     -#define LFIND(T, k, a, n)                                             \
     +#define LFIND(T, ...)       LFIND_(typeas(T), __VA_ARGS__)
     +#define LFIND_(T, k, a, n)                                            \
    - (                                                                     \
    -   (register T *){                                               \
    -           lfind_((register const T *){k}, (register const T *){a}, n, sizeof(T), CMP(T))\
    + ({                                                                    \
    +   _Generic(k, T *: 0, const T *: 0);                            \
    +   _Generic(a, T *: 0, const T *: 0);                            \
     
      ## lib/search/l/lsearch.h ##
     @@
    @@ lib/search/l/lsearch.h
     -#define LSEARCH(T, k, a, n)                                           \
     +#define LSEARCH(T, ...)       LSEARCH_(typeas(T), __VA_ARGS__)
     +#define LSEARCH_(T, k, a, n)                                          \
    - (                                                                     \
    -   (register T *){                                               \
    -           lsearch((register const T *){k}, (register T *){a}, n, sizeof(T), CMP(T))\
    + ({                                                                    \
    +   _Generic(k, T *: 0, const T *: 0);                            \
    +   _Generic(a, T *: 0);                                          \
     
      ## lib/search/sort/qsort.h ##
     @@
    @@ lib/search/sort/qsort.h
     +#include "sizeof.h"
      
      
    --#define QSORT(T, a, n)  qsort((register T *){a}, n, sizeof(T), CMP(T))
    +-#define QSORT(T, a, n)  do                                            \
     +#define QSORT(T, ...)    QSORT_(typeas(T), __VA_ARGS__)
    -+#define QSORT_(T, a, n)  qsort((register T *){a}, n, sizeof(T), CMP(T))
    - 
    - 
    - #endif  // include guard
    ++#define QSORT_(T, a, n)  do                                           \
    + {                                                                     \
    +   _Generic(a, T *: 0);                                          \
    +   qsort(a, n, sizeof(T), CMP(T));                               \
 8:  052a64b42 !  8:  bf03fb10b lib/alloc/: reallocarray[f]_(): Add helper macros to handle n?:1
    @@ lib/alloc/realloc.h
     @@
      #define REALLOC(p, n, T)   REALLOC_(p, n, typeas(T))
      #define REALLOC_(p, n, T)                                             \
    - (                                                                     \
    --  _Generic(p, T *: (register T *){reallocarray(p, (n) ?: 1, sizeof(T))}) \
    -+  _Generic(p, T *: (register T *){reallocarray_(p, n, sizeof(T))}) \
    - )
    + ({                                                                    \
    +-  _Generic(p, T *: (T *){reallocarray(p, (n) ?: 1, sizeof(T))});\
    ++  _Generic(p, T *: (T *){reallocarray_(p, n, sizeof(T))});      \
    + })
      
     +#define reallocarray_(p, n, size)  reallocarray(p, (n) ?: 1, (size) ?: 1)
     +
    @@ lib/alloc/reallocf.h
     @@
      #define REALLOCF(p, n, T)   REALLOCF_(p, n, typeas(T))
      #define REALLOCF_(p, n, T)                                            \
    - (                                                                     \
    --  _Generic(p, T *: (register T *){reallocarrayf(p, (n) ?: 1, sizeof(T))}) \
    -+  _Generic(p, T *: (register T *){reallocarrayf_(p, n, sizeof(T))}) \
    - )
    + ({                                                                    \
    +-  _Generic(p, T *: (T *){reallocarrayf(p, (n) ?: 1, sizeof(T))});\
    ++  _Generic(p, T *: (T *){reallocarrayf_(p, n, sizeof(T))});     \
    + })
      
     +#define reallocarrayf_(p, n, size)  reallocarrayf(p, (n) ?: 1, (size) ?: 1)
     +
 9:  3b0e2ef01 !  9:  a89b93c84 lib/alloc/: REALLOC[F](): Use compound literal to avoid _Generic(3)
    @@ Metadata
     Author: Alejandro Colomar <[email protected]>
     
      ## Commit message ##
    -    lib/alloc/: REALLOC[F](): Use compound literal to avoid _Generic(3)
    +    lib/alloc/: REALLOC[F](): Move _Generic(3) to separate line
     
    -    Compound literals are much more portable (standardized in ISO C99) than
    -    _Generic(3) (standardized in ISO C11).
    -
    -    Compound literals have a small difference: they accept a void* as input.
    -    This makes these APIs slightly less strict.  However, that shouldn't be
    -    a big problem: most APIs in C accept void*, and having one that doesn't
    -    accept them wouldn't be a significant safety measure.
    -
    -    On the other hand, this makes these macros more useful to arbitrary
    -    programmers, as they would rightfully expect void* to be valid input to
    -    any API.
    -
    -    Instead, the focus should be in reducing void* variables.  We do indeed
    -    use very few of those.  And I'll work in removing more of those.
    +    This should be more readable.
     
         Signed-off-by: Alejandro Colomar <[email protected]>
     
    @@ lib/alloc/realloc.h
     @@
      #define REALLOC(p, n, T)   REALLOC_(p, n, typeas(T))
      #define REALLOC_(p, n, T)                                             \
    - (                                                                     \
    --  _Generic(p, T *: (register T *){reallocarray_(p, n, sizeof(T))}) \
    -+  (register T *){reallocarray_((register T *){p}, n, sizeof(T))}\
    - )
    + ({                                                                    \
    +-  _Generic(p, T *: (T *){reallocarray_(p, n, sizeof(T))});      \
    ++  _Generic(p, T *: 0);                                          \
    ++  (T *){reallocarray_(p, n, sizeof(T))};                        \
    + })
      
      #define reallocarray_(p, n, size)  reallocarray(p, (n) ?: 1, (size) ?: 1)
     
    @@ lib/alloc/reallocf.h
     @@
      #define REALLOCF(p, n, T)   REALLOCF_(p, n, typeas(T))
      #define REALLOCF_(p, n, T)                                            \
    - (                                                                     \
    --  _Generic(p, T *: (register T *){reallocarrayf_(p, n, sizeof(T))}) \
    -+  (register T *){reallocarrayf_((register T *){p}, n, sizeof(T))}\
    - )
    + ({                                                                    \
    +-  _Generic(p, T *: (T *){reallocarrayf_(p, n, sizeof(T))});     \
    ++  _Generic(p, T *: 0);                                          \
    ++  (T *){reallocarrayf_(p, n, sizeof(T))};                       \
    + })
      
      #define reallocarrayf_(p, n, size)  reallocarrayf(p, (n) ?: 1, (size) ?: 1)
10:  7cff553b7 ! 10:  5d43d734b lib/search/: Split APIs
    @@ lib/search/l/lfind.h
     +// lfind_T - linear find type-safe
     +#define lfind_T(T, ...)            lfind_T_(typeas(T), __VA_ARGS__)
     +#define lfind_T_(T, k, a, n, cmp)                                     \
    - (                                                                     \
    -   (register T *){                                               \
    --          lfind_((register const T *){k}, (register const T *){a}, n, sizeof(T), CMP(T))\
    -+          lfind_((register const T *){k}, (register const T *){a}, n, sizeof(T), cmp)\
    -   }                                                             \
    - )
    + ({                                                                    \
    +   _Generic(k, T *: 0, const T *: 0);                            \
    +   _Generic(a, T *: 0, const T *: 0);                            \
    +-  (T *){lfind_(k, a, n, sizeof(T), CMP(T))};                    \
    ++  (T *){lfind_(k, a, n, sizeof(T), cmp)};                       \
    + })
      
     +#define LFIND(T, ...)  lfind_T(T, __VA_ARGS__, CMP(T))
     +
    @@ lib/search/l/lsearch.h
     +// lsearch_T - linear search-and-insert type-safe
     +#define lsearch_T(T, ...)            lsearch_T_(typeas(T), __VA_ARGS__)
     +#define lsearch_T_(T, k, a, n, cmp)                                   \
    - (                                                                     \
    -   (register T *){                                               \
    --          lsearch((register const T *){k}, (register T *){a}, n, sizeof(T), CMP(T))\
    -+          lsearch((register const T *){k}, (register T *){a}, n, sizeof(T), cmp)\
    -   }                                                             \
    - )
    + ({                                                                    \
    +   _Generic(k, T *: 0, const T *: 0);                            \
    +   _Generic(a, T *: 0);                                          \
    +-  (T *){lsearch(k, a, n, sizeof(T), CMP(T))};                   \
    ++  (T *){lsearch(k, a, n, sizeof(T), cmp)};                      \
    + })
      
     +#define LSEARCH(T, ...)  lsearch_T(T, __VA_ARGS__, CMP(T))
     +
    @@ lib/search/sort/qsort.h
      
      
     -#define QSORT(T, ...)    QSORT_(typeas(T), __VA_ARGS__)
    --#define QSORT_(T, a, n)  qsort((register T *){a}, n, sizeof(T), CMP(T))
    +-#define QSORT_(T, a, n)  do                                           \
     +// qsort_T - sort type-safe
     +#define qsort_T(T, ...)   qsort_T_(typeas(T), __VA_ARGS__)
    -+#define qsort_T_(T, a, n, cmp)  qsort((register T *){a}, n, sizeof(T), cmp)
    -+
    -+#define QSORT(T, ...)  qsort_T(T, __VA_ARGS__, CMP(T))
    ++#define qsort_T_(T, a, n, cmp)                                        \
    + {                                                                     \
    +   _Generic(a, T *: 0);                                          \
    +-  qsort(a, n, sizeof(T), CMP(T));                               \
    ++  qsort(a, n, sizeof(T), cmp);                                  \
    + } while (0)
      
    ++#define QSORT(T, ...)  qsort_T(T, __VA_ARGS__, CMP(T))
    ++
      
      #endif  // include guard
11:  cd0b2711b ! 11:  3172b8c3b lib/, src/: Rename REALLOCF() => reallocf_T()
    @@ lib/alloc/reallocf.h
     +// reallocf_T - realloc free-on-error type-safe
     +#define reallocf_T(p, n, T)   reallocf_T_(p, n, typeas(T))
     +#define reallocf_T_(p, n, T)                                          \
    - (                                                                     \
    -   (register T *){reallocarrayf_((register T *){p}, n, sizeof(T))}\
    - )
    + ({                                                                    \
    +   _Generic(p, T *: 0);                                          \
    +   (T *){reallocarrayf_(p, n, sizeof(T))};                       \
     @@
      #define reallocarrayf_(p, n, size)  reallocarrayf(p, (n) ?: 1, (size) ?: 1)
      
12:  99755e67f ! 12:  27fed47ff lib/: Rename REALLOC() => realloc_T()
    @@ lib/alloc/realloc.h
     +// realloc_T - realloc type-safe
     +#define realloc_T(p, n, T)   realloc_T_(p, n, typeas(T))
     +#define realloc_T_(p, n, T)                                           \
    - (                                                                     \
    -   (register T *){reallocarray_((register T *){p}, n, sizeof(T))}\
    - )
    + ({                                                                    \
    +   _Generic(p, T *: 0);                                          \
    +   (T *){reallocarray_(p, n, sizeof(T))};                        \
     @@
      #define reallocarray_(p, n, size)  reallocarray(p, (n) ?: 1, (size) ?: 1)
      
13:  b6a3d6244 = 13:  7e8c5208f lib/: Rename XREALLOC() => xrealloc_T()
14:  76fb271aa ! 14:  d0b2991f5 lib/: Rename MALLOC() => malloc_T()
    @@ lib/alloc/malloc.h
     +// malloc_T - malloc type-safe
     +#define malloc_T(n, T)   malloc_T_(n, typeas(T))
     +#define malloc_T_(n, T)                                               \
    - (                                                                     \
    -   (register T *){mallocarray(n, sizeof(T))}                     \
    - )
    + ({                                                                    \
    +   (T *){mallocarray(n, sizeof(T))};                             \
    + })
      
      
     -#define XMALLOC(n, T)  exit_if_null(MALLOC(n, T))
15:  1ebc00006 ! 15:  da1b38730 lib/: Rename XMALLOC() => xmalloc_T()
    @@ Commit message
     
      ## lib/alloc/malloc.h ##
     @@
    - )
    + })
      
      
     -#define XMALLOC(n, T)  exit_if_null(malloc_T(n, T))
16:  28a963664 ! 16:  0789dc161 lib/: Rename CALLOC() => calloc_T()
    @@ lib/alloc/calloc.h
     +// calloc_T - calloc type-safe
     +#define calloc_T(n, T)   calloc_T_(n, typeas(T))
     +#define calloc_T_(n, T)                                               \
    - (                                                                     \
    -   (register T *){calloc(n, sizeof(T))}                          \
    - )
    + ({                                                                    \
    +   (T *){calloc(n, sizeof(T))};                                  \
    + })
      
      
     -#define XCALLOC(n, T)  exit_if_null(CALLOC(n, T))
17:  8faece4a5 ! 17:  204109bea lib/: Rename XCALLOC() => xcalloc_T()
    @@ Commit message
     
      ## lib/alloc/calloc.h ##
     @@
    - )
    + })
      
      
     -#define XCALLOC(n, T)  exit_if_null(calloc_T(n, T))
18:  2ef110cc5 ! 18:  685810adf lib/search/: lsearch_T(): Don't return anything
    @@ lib/search/l/lsearch.h
      // lsearch_T - linear search-and-insert type-safe
      #define lsearch_T(T, ...)            lsearch_T_(typeas(T), __VA_ARGS__)
     -#define lsearch_T_(T, k, a, n, cmp)                                   \
    --(                                                                     \
    --  (register T *){                                               \
    --          lsearch((register const T *){k}, (register T *){a}, n, sizeof(T), cmp)\
    --  }                                                             \
    --)
    +-({                                                                    \
     +#define lsearch_T_(T, k, a, n, cmp)  do                               \
     +{                                                                     \
    -+  lsearch((register const T *){k}, (register T *){a}, n, sizeof(T), cmp);\
    +   _Generic(k, T *: 0, const T *: 0);                            \
    +   _Generic(a, T *: 0);                                          \
    +-  (T *){lsearch(k, a, n, sizeof(T), cmp)};                      \
    +-})
    ++  lsearch(k, a, n, sizeof(T), cmp);                             \
     +} while (0)
      
      #define LSEARCH(T, ...)  lsearch_T(T, __VA_ARGS__, CMP(T))
v8
  • Reorder commits. This should make it easier to review. Each commit affects less code now.
  • Add missing do in do-while. I probably removed it by accident in a previous rebase operation.
interdiff
$ git diff gh/T..T
diff --git a/lib/search/sort/qsort.h b/lib/search/sort/qsort.h
index 728d2519a..471fdec86 100644
--- a/lib/search/sort/qsort.h
+++ b/lib/search/sort/qsort.h
@@ -15,8 +15,8 @@
 
 
 // qsort_T - sort type-safe
-#define qsort_T(T, ...)   qsort_T_(typeas(T), __VA_ARGS__)
-#define qsort_T_(T, a, n, cmp)                                        \
+#define qsort_T(T, ...)         qsort_T_(typeas(T), __VA_ARGS__)
+#define qsort_T_(T, a, n, cmp)  do                                    \
 {                                                                     \
        _Generic(a, T *: 0);                                          \
        qsort(a, n, sizeof(T), cmp);                                  \
range-diff
$ git rd --creation-factor=99
 1:  85b410574 =  1:  85b410574 lib/: Use a consistent name for macro arguments representing a type name
 3:  7150d4349 !  2:  8914daf44 lib/search/, lib/, src/: Add a type parameter to the type-safe macros
    @@ Metadata
      ## Commit message ##
         lib/search/, lib/, src/: Add a type parameter to the type-safe macros
     
    -    This simplifies the implementation, removing the need for
    -    _Static_assert(3) and is_same_type().  The implicit conversion rules
    -    guarantee the correct types in a more elegant way.
    +    This simplifies the implementation, allowing us to use _Generic(3) to
    +    replace _Static_assert(3), is_same_type(), and local variables.
    +
    +    Local variables in macros can cause issues when nesting such macros.
     
         This also makes the code more readable, by having the type explicitly
         stated at call site.
    @@ lib/search/l/lfind.h
      ({                                                                    \
     -  __auto_type  k_ = k;                                          \
     -  __auto_type  a_ = a;                                          \
    -+  const T  *k_ = k;                                             \
    -+  const T  *a_ = a;                                             \
    -                                                                       \
    +-                                                                      \
     -  static_assert(is_same_typeof(k_, a_), "");                    \
     -                                                                      \
    --  (typeof(k_)){lfind_(k_, a_, n, sizeof(*k_), CMP(typeof(k_)))};\
    -+  (T *){lfind_(k_, a_, n, sizeof(T), CMP(T *))};                \
    +-  (typeof(k_)) lfind_(k_, a_, n, sizeof(*k_), CMP(typeof(k_))); \
    ++  _Generic(k, T *: 0, const T *: 0);                            \
    ++  _Generic(a, T *: 0, const T *: 0);                            \
    ++  (T *) lfind_(k, a, n, sizeof(T), CMP(T *));                   \
      })
      
      
    @@ lib/search/l/lsearch.h
      ({                                                                    \
     -  __auto_type  k_ = k;                                          \
     -  __auto_type  a_ = a;                                          \
    -+  const T  *k_ = k;                                             \
    -+  T        *a_ = a;                                             \
    -                                                                       \
    +-                                                                      \
     -  static_assert(is_same_typeof(k_, a_), "");                    \
     -                                                                      \
    --  (typeof(k_)){lsearch(k_, a_, n, sizeof(*k_), CMP(typeof(k_)))};\
    -+  (T *){lsearch(k_, a_, n, sizeof(T), CMP(T *))};               \
    +-  (typeof(k_)) lsearch(k_, a_, n, sizeof(*k_), CMP(typeof(k_)));\
    ++  _Generic(k, T *: 0, const T *: 0);                            \
    ++  _Generic(a, T *: 0);                                          \
    ++  (T *) lsearch(k, a, n, sizeof(T), CMP(T *));                  \
      })
      
      
    @@ lib/search/sort/qsort.h
     +#define QSORT(T, a, n)  do                                            \
      {                                                                     \
     -  __auto_type  p_ = a;                                          \
    -+  T  *p_ = a;                                                   \
    -                                                                       \
    +-                                                                      \
     -  qsort(p_, n, sizeof(*p_), CMP(typeof(p_)));                   \
    -+  qsort(p_, n, sizeof(T), CMP(T *));                            \
    ++  _Generic(a, T *: 0);                                          \
    ++  qsort(a, n, sizeof(T), CMP(T *));                             \
      } while (0)
      
      
 4:  9ed48c5d2 !  3:  d95b19bdb lib/search/: Simplify CMP()
    @@ lib/search/cmp/cmp.h
     @@
      #define CMP(T)                                                        \
      (                                                                     \
    -   _Generic((T){},                                               \
    +   _Generic((T) 0,                                               \
     -          int *:            cmp_int,                            \
     -          long *:           cmp_long,                           \
     -          unsigned int *:   cmp_uint,                           \
    @@ lib/search/cmp/cmp.h
     
      ## lib/search/l/lfind.h ##
     @@
    -   const T  *k_ = k;                                             \
    -   const T  *a_ = a;                                             \
    -                                                                       \
    --  (T *){lfind_(k_, a_, n, sizeof(T), CMP(T *))};                \
    -+  (T *){lfind_(k_, a_, n, sizeof(T), CMP(T))};                  \
    + ({                                                                    \
    +   _Generic(k, T *: 0, const T *: 0);                            \
    +   _Generic(a, T *: 0, const T *: 0);                            \
    +-  (T *) lfind_(k, a, n, sizeof(T), CMP(T *));                   \
    ++  (T *) lfind_(k, a, n, sizeof(T), CMP(T));                     \
      })
      
      
     
      ## lib/search/l/lsearch.h ##
     @@
    -   const T  *k_ = k;                                             \
    -   T        *a_ = a;                                             \
    -                                                                       \
    --  (T *){lsearch(k_, a_, n, sizeof(T), CMP(T *))};               \
    -+  (T *){lsearch(k_, a_, n, sizeof(T), CMP(T))};                 \
    + ({                                                                    \
    +   _Generic(k, T *: 0, const T *: 0);                            \
    +   _Generic(a, T *: 0);                                          \
    +-  (T *) lsearch(k, a, n, sizeof(T), CMP(T *));                  \
    ++  (T *) lsearch(k, a, n, sizeof(T), CMP(T));                    \
      })
      
      
     
      ## lib/search/sort/qsort.h ##
     @@
    + #define QSORT(T, a, n)  do                                            \
      {                                                                     \
    -   T  *p_ = a;                                                   \
    -                                                                       \
    --  qsort(p_, n, sizeof(T), CMP(T *));                            \
    -+  qsort(p_, n, sizeof(T), CMP(T));                              \
    +   _Generic(a, T *: 0);                                          \
    +-  qsort(a, n, sizeof(T), CMP(T *));                             \
    ++  qsort(a, n, sizeof(T), CMP(T));                               \
      } while (0)
      
      
10:  5d43d734b !  4:  fbae64c81 lib/search/: Split APIs
    @@ Commit message
     
      ## lib/search/l/lfind.h ##
     @@
    - #include "sizeof.h"
    + #include "search/cmp/cmp.h"
      
      
    --#define LFIND(T, ...)       LFIND_(typeas(T), __VA_ARGS__)
    --#define LFIND_(T, k, a, n)                                            \
    +-#define LFIND(T, k, a, n)                                             \
     +// lfind_T - linear find type-safe
    -+#define lfind_T(T, ...)            lfind_T_(typeas(T), __VA_ARGS__)
    -+#define lfind_T_(T, k, a, n, cmp)                                     \
    ++#define lfind_T(T, k, a, n, cmp)                                      \
      ({                                                                    \
        _Generic(k, T *: 0, const T *: 0);                            \
        _Generic(a, T *: 0, const T *: 0);                            \
    --  (T *){lfind_(k, a, n, sizeof(T), CMP(T))};                    \
    -+  (T *){lfind_(k, a, n, sizeof(T), cmp)};                       \
    +-  (T *) lfind_(k, a, n, sizeof(T), CMP(T));                     \
    ++  (T *) lfind_(k, a, n, sizeof(T), cmp);                        \
      })
      
     +#define LFIND(T, ...)  lfind_T(T, __VA_ARGS__, CMP(T))
    @@ lib/search/l/lfind.h
     
      ## lib/search/l/lsearch.h ##
     @@
    - #include "sizeof.h"
    + #include "search/cmp/cmp.h"
      
      
    --#define LSEARCH(T, ...)       LSEARCH_(typeas(T), __VA_ARGS__)
    --#define LSEARCH_(T, k, a, n)                                          \
    +-#define LSEARCH(T, k, a, n)                                           \
     +// lsearch_T - linear search-and-insert type-safe
    -+#define lsearch_T(T, ...)            lsearch_T_(typeas(T), __VA_ARGS__)
    -+#define lsearch_T_(T, k, a, n, cmp)                                   \
    ++#define lsearch_T(T, k, a, n, cmp)                                    \
      ({                                                                    \
        _Generic(k, T *: 0, const T *: 0);                            \
        _Generic(a, T *: 0);                                          \
    --  (T *){lsearch(k, a, n, sizeof(T), CMP(T))};                   \
    -+  (T *){lsearch(k, a, n, sizeof(T), cmp)};                      \
    +-  (T *) lsearch(k, a, n, sizeof(T), CMP(T));                    \
    ++  (T *) lsearch(k, a, n, sizeof(T), cmp);                       \
      })
      
     +#define LSEARCH(T, ...)  lsearch_T(T, __VA_ARGS__, CMP(T))
    @@ lib/search/l/lsearch.h
     
      ## lib/search/sort/qsort.h ##
     @@
    - #include "sizeof.h"
    + #include "search/cmp/cmp.h"
      
      
    --#define QSORT(T, ...)    QSORT_(typeas(T), __VA_ARGS__)
    --#define QSORT_(T, a, n)  do                                           \
    +-#define QSORT(T, a, n)  do                                            \
     +// qsort_T - sort type-safe
    -+#define qsort_T(T, ...)   qsort_T_(typeas(T), __VA_ARGS__)
    -+#define qsort_T_(T, a, n, cmp)                                        \
    ++#define qsort_T(T, a, n, cmp)  do                                     \
      {                                                                     \
        _Generic(a, T *: 0);                                          \
     -  qsort(a, n, sizeof(T), CMP(T));                               \
 5:  482f4a460 !  5:  a1eeb89b9 lib/sizeof.h: typeas(): Add macro
    @@ lib/sizeof.h
      
     +#define typeas(T)            typeof((T){})
     +
    - #define ssizeof(x)           ({(ssize_t){sizeof(x)};})
    + #define ssizeof(x)           ((ssize_t) sizeof(x))
      #define memberof(T, member)  ((T){}.member)
      #define WIDTHOF(x)           (sizeof(x) * CHAR_BIT)
 7:  b79dda9d5 !  6:  d0f7a93b1 lib/{alloc,search}/: Use typeas() to add support for arbitrary types
    @@ lib/alloc/calloc.h
     -#define CALLOC(n, T)                                                  \
     +#define CALLOC(n, T)   CALLOC_(n, typeas(T))
     +#define CALLOC_(n, T)                                                 \
    - ({                                                                    \
    -   (T *){calloc(n, sizeof(T))};                                  \
    - })
    + (                                                                     \
    +   (T *) calloc(n, sizeof(T))                                    \
    + )
     
      ## lib/alloc/malloc.h ##
     @@
    @@ lib/alloc/malloc.h
     -#define MALLOC(n, T)                                                  \
     +#define MALLOC(n, T)   MALLOC_(n, typeas(T))
     +#define MALLOC_(n, T)                                                 \
    - ({                                                                    \
    -   (T *){mallocarray(n, sizeof(T))};                             \
    - })
    + (                                                                     \
    +   (T *) mallocarray(n, sizeof(T))                               \
    + )
     
      ## lib/alloc/realloc.h ##
     @@
    @@ lib/alloc/realloc.h
     -#define REALLOC(p, n, T)                                              \
     +#define REALLOC(p, n, T)   REALLOC_(p, n, typeas(T))
     +#define REALLOC_(p, n, T)                                             \
    - ({                                                                    \
    -   _Generic(p, T *: (T *){reallocarray(p, (n) ?: 1, sizeof(T))});\
    - })
    + (                                                                     \
    +   _Generic(p, T *: (T *) reallocarray(p, (n) ?: 1, sizeof(T)))  \
    + )
     
      ## lib/alloc/reallocf.h ##
     @@
    @@ lib/alloc/reallocf.h
     -#define REALLOCF(p, n, T)                                             \
     +#define REALLOCF(p, n, T)   REALLOCF_(p, n, typeas(T))
     +#define REALLOCF_(p, n, T)                                            \
    - ({                                                                    \
    -   _Generic(p, T *: (T *){reallocarrayf(p, (n) ?: 1, sizeof(T))});\
    - })
    + (                                                                     \
    +   _Generic(p, T *: (T *) reallocarrayf(p, (n) ?: 1, sizeof(T))) \
    + )
     
      ## lib/search/l/lfind.h ##
     @@
    @@ lib/search/l/lfind.h
     +#include "sizeof.h"
      
      
    --#define LFIND(T, k, a, n)                                             \
    -+#define LFIND(T, ...)       LFIND_(typeas(T), __VA_ARGS__)
    -+#define LFIND_(T, k, a, n)                                            \
    + // lfind_T - linear find type-safe
    +-#define lfind_T(T, k, a, n, cmp)                                      \
    ++#define lfind_T(T, ...)            lfind_T_(typeas(T), __VA_ARGS__)
    ++#define lfind_T_(T, k, a, n, cmp)                                     \
      ({                                                                    \
        _Generic(k, T *: 0, const T *: 0);                            \
        _Generic(a, T *: 0, const T *: 0);                            \
    @@ lib/search/l/lsearch.h
     +#include "sizeof.h"
      
      
    --#define LSEARCH(T, k, a, n)                                           \
    -+#define LSEARCH(T, ...)       LSEARCH_(typeas(T), __VA_ARGS__)
    -+#define LSEARCH_(T, k, a, n)                                          \
    + // lsearch_T - linear search-and-insert type-safe
    +-#define lsearch_T(T, k, a, n, cmp)                                    \
    ++#define lsearch_T(T, ...)            lsearch_T_(typeas(T), __VA_ARGS__)
    ++#define lsearch_T_(T, k, a, n, cmp)                                   \
      ({                                                                    \
        _Generic(k, T *: 0, const T *: 0);                            \
        _Generic(a, T *: 0);                                          \
    @@ lib/search/sort/qsort.h
     +#include "sizeof.h"
      
      
    --#define QSORT(T, a, n)  do                                            \
    -+#define QSORT(T, ...)    QSORT_(typeas(T), __VA_ARGS__)
    -+#define QSORT_(T, a, n)  do                                           \
    + // qsort_T - sort type-safe
    +-#define qsort_T(T, a, n, cmp)  do                                     \
    ++#define qsort_T(T, ...)         qsort_T_(typeas(T), __VA_ARGS__)
    ++#define qsort_T_(T, a, n, cmp)  do                                    \
      {                                                                     \
        _Generic(a, T *: 0);                                          \
    -   qsort(a, n, sizeof(T), CMP(T));                               \
    +   qsort(a, n, sizeof(T), cmp);                                  \
 8:  bf03fb10b !  7:  b8aacd5e5 lib/alloc/: reallocarray[f]_(): Add helper macros to handle n?:1
    @@ lib/alloc/realloc.h
     @@
      #define REALLOC(p, n, T)   REALLOC_(p, n, typeas(T))
      #define REALLOC_(p, n, T)                                             \
    - ({                                                                    \
    --  _Generic(p, T *: (T *){reallocarray(p, (n) ?: 1, sizeof(T))});\
    -+  _Generic(p, T *: (T *){reallocarray_(p, n, sizeof(T))});      \
    - })
    + (                                                                     \
    +-  _Generic(p, T *: (T *) reallocarray(p, (n) ?: 1, sizeof(T)))  \
    ++  _Generic(p, T *: (T *) reallocarray_(p, n, sizeof(T)))        \
    + )
      
     +#define reallocarray_(p, n, size)  reallocarray(p, (n) ?: 1, (size) ?: 1)
     +
    @@ lib/alloc/reallocf.h
     @@
      #define REALLOCF(p, n, T)   REALLOCF_(p, n, typeas(T))
      #define REALLOCF_(p, n, T)                                            \
    - ({                                                                    \
    --  _Generic(p, T *: (T *){reallocarrayf(p, (n) ?: 1, sizeof(T))});\
    -+  _Generic(p, T *: (T *){reallocarrayf_(p, n, sizeof(T))});     \
    - })
    + (                                                                     \
    +-  _Generic(p, T *: (T *) reallocarrayf(p, (n) ?: 1, sizeof(T))) \
    ++  _Generic(p, T *: (T *) reallocarrayf_(p, n, sizeof(T)))       \
    + )
      
     +#define reallocarrayf_(p, n, size)  reallocarrayf(p, (n) ?: 1, (size) ?: 1)
     +
 2:  b0e13521e !  8:  ca2c62660 lib/: Use compound literals to avoid casts
    @@ Commit message
         diagnostics--.
     
         Compound literals are lvalues, which means their address can be taken,
    -    and they can also be assigned to.  To avoid this, we perform lvalue
    +    and they can also be assigned to.  To avoid this, we force lvalue
         conversion through a statement expression.
     
         Signed-off-by: Alejandro Colomar <[email protected]>
    @@ Commit message
      ## lib/alloc/calloc.h ##
     @@
      
    - 
    - #define CALLOC(n, T)                                                  \
    + #define CALLOC(n, T)   CALLOC_(n, typeas(T))
    + #define CALLOC_(n, T)                                                 \
     -(                                                                     \
     -  (T *) calloc(n, sizeof(T))                                    \
     -)
    @@ lib/alloc/calloc.h
      ## lib/alloc/malloc.h ##
     @@
      
    - 
    - #define MALLOC(n, T)                                                  \
    + #define MALLOC(n, T)   MALLOC_(n, typeas(T))
    + #define MALLOC_(n, T)                                                 \
     -(                                                                     \
     -  (T *) mallocarray(n, sizeof(T))                               \
     -)
    @@ lib/alloc/malloc.h
      ## lib/alloc/realloc.h ##
     @@
      
    - 
    - #define REALLOC(p, n, T)                                              \
    + #define REALLOC(p, n, T)   REALLOC_(p, n, typeas(T))
    + #define REALLOC_(p, n, T)                                             \
     -(                                                                     \
    --  _Generic(p, T *: (T *) reallocarray(p, (n) ?: 1, sizeof(T)))  \
    +-  _Generic(p, T *: (T *) reallocarray_(p, n, sizeof(T)))        \
     -)
     +({                                                                    \
    -+  _Generic(p, T *: (T *){reallocarray(p, (n) ?: 1, sizeof(T))});\
    ++  _Generic(p, T *: (T *){reallocarray_(p, n, sizeof(T))});      \
     +})
      
    + #define reallocarray_(p, n, size)  reallocarray(p, (n) ?: 1, (size) ?: 1)
      
    - #define XREALLOC(p, n, T)  exit_if_null(REALLOC(p, n, T))
     
      ## lib/alloc/reallocf.h ##
     @@
      
    - 
    - #define REALLOCF(p, n, T)                                             \
    + #define REALLOCF(p, n, T)   REALLOCF_(p, n, typeas(T))
    + #define REALLOCF_(p, n, T)                                            \
     -(                                                                     \
    --  _Generic(p, T *: (T *) reallocarrayf(p, (n) ?: 1, sizeof(T))) \
    +-  _Generic(p, T *: (T *) reallocarrayf_(p, n, sizeof(T)))       \
     -)
     +({                                                                    \
    -+  _Generic(p, T *: (T *){reallocarrayf(p, (n) ?: 1, sizeof(T))});\
    ++  _Generic(p, T *: (T *){reallocarrayf_(p, n, sizeof(T))});     \
     +})
      
    + #define reallocarrayf_(p, n, size)  reallocarrayf(p, (n) ?: 1, (size) ?: 1)
      
    - ATTR_ALLOC_SIZE(2, 3)
     
      ## lib/atoi/a2i/a2i.h ##
     @@
    @@ lib/search/cmp/cmp.h
      (                                                                     \
     -  _Generic((T) 0,                                               \
     +  _Generic((T){},                                               \
    -           int *:            cmp_int,                            \
    -           long *:           cmp_long,                           \
    -           unsigned int *:   cmp_uint,                           \
    +           int:            cmp_int,                              \
    +           long:           cmp_long,                             \
    +           unsigned int:   cmp_uint,                             \
     
      ## lib/search/l/lfind.h ##
     @@
    -                                                                       \
    -   static_assert(is_same_typeof(k_, a_), "");                    \
    -                                                                       \
    --  (typeof(k_)) lfind_(k_, a_, n, sizeof(*k_), CMP(typeof(k_))); \
    -+  (typeof(k_)){lfind_(k_, a_, n, sizeof(*k_), CMP(typeof(k_)))};\
    + ({                                                                    \
    +   _Generic(k, T *: 0, const T *: 0);                            \
    +   _Generic(a, T *: 0, const T *: 0);                            \
    +-  (T *) lfind_(k, a, n, sizeof(T), cmp);                        \
    ++  (T *){lfind_(k, a, n, sizeof(T), cmp)};                       \
      })
      
    - 
    + #define LFIND(T, ...)  lfind_T(T, __VA_ARGS__, CMP(T))
     
      ## lib/search/l/lsearch.h ##
     @@
    -                                                                       \
    -   static_assert(is_same_typeof(k_, a_), "");                    \
    -                                                                       \
    --  (typeof(k_)) lsearch(k_, a_, n, sizeof(*k_), CMP(typeof(k_)));\
    -+  (typeof(k_)){lsearch(k_, a_, n, sizeof(*k_), CMP(typeof(k_)))};\
    + ({                                                                    \
    +   _Generic(k, T *: 0, const T *: 0);                            \
    +   _Generic(a, T *: 0);                                          \
    +-  (T *) lsearch(k, a, n, sizeof(T), cmp);                       \
    ++  (T *){lsearch(k, a, n, sizeof(T), cmp)};                      \
      })
      
    - 
    + #define LSEARCH(T, ...)  lsearch_T(T, __VA_ARGS__, CMP(T))
     
      ## lib/sizeof.h ##
     @@
    - #include <sys/types.h>
      
    + #define typeas(T)            typeof((T){})
      
     -#define ssizeof(x)           ((ssize_t) sizeof(x))
     +#define ssizeof(x)           ({(ssize_t){sizeof(x)};})
 6:  a7733d2d1 <  -:  --------- lib/search/: Use _Generic(3) to avoid local variables
 9:  a89b93c84 =  9:  3168abcfe lib/alloc/: REALLOC[F](): Move _Generic(3) to separate line
11:  3172b8c3b = 10:  869afab38 lib/, src/: Rename REALLOCF() => reallocf_T()
12:  27fed47ff = 11:  c8bfddd41 lib/: Rename REALLOC() => realloc_T()
13:  7e8c5208f = 12:  3cb99aba0 lib/: Rename XREALLOC() => xrealloc_T()
14:  d0b2991f5 = 13:  217eba94b lib/: Rename MALLOC() => malloc_T()
15:  da1b38730 = 14:  e8acd6c67 lib/: Rename XMALLOC() => xmalloc_T()
16:  0789dc161 = 15:  3e6a0b004 lib/: Rename CALLOC() => calloc_T()
17:  204109bea = 16:  1543c7668 lib/: Rename XCALLOC() => xcalloc_T()
18:  685810adf = 17:  1ea155970 lib/search/: lsearch_T(): Don't return anything
v8b
  • Rebase
$ git rd 
 1:  85b410574 !  1:  b4044b01d lib/: Use a consistent name for macro arguments representing a type name
    @@ lib/alloc/reallocf.h
      
      
     
    - ## lib/atoi/a2i/a2i.h ##
    -@@
    -  */
    - 
    - 
    --#define a2i(TYPE, n, s, ...)                                                  \
    -+#define a2i(T, n, s, ...)                                                     \
    - (                                                                             \
    --  _Generic((void (*)(TYPE, typeof(s))) 0,                               \
    -+  _Generic((void (*)(T, typeof(s))) 0,                                  \
    -           void (*)(short,              const char *):  a2sh_c,          \
    -           void (*)(short,              const void *):  a2sh_c,          \
    -           void (*)(short,              char *):        a2sh_nc,         \
    -
      ## lib/search/cmp/cmp.h ##
     @@
      #include "config.h"
 2:  8914daf44 =  2:  1725bb81e lib/search/, lib/, src/: Add a type parameter to the type-safe macros
 3:  d95b19bdb =  3:  0ae8aac83 lib/search/: Simplify CMP()
 4:  fbae64c81 =  4:  0bb83a0bc lib/search/: Split APIs
 5:  a1eeb89b9 =  5:  c8b88d8f3 lib/sizeof.h: typeas(): Add macro
 6:  d0f7a93b1 =  6:  8557266d3 lib/{alloc,search}/: Use typeas() to add support for arbitrary types
 7:  b8aacd5e5 =  7:  666f7a4e9 lib/alloc/: reallocarray[f]_(): Add helper macros to handle n?:1
 8:  ca2c62660 !  8:  435059189 lib/: Use compound literals to avoid casts
    @@ lib/alloc/reallocf.h
      #define reallocarrayf_(p, n, size)  reallocarrayf(p, (n) ?: 1, (size) ?: 1)
      
     
    - ## lib/atoi/a2i/a2i.h ##
    -@@
    - 
    - #define a2i(T, n, s, ...)                                                     \
    - (                                                                             \
    --  _Generic((void (*)(T, typeof(s))) 0,                                  \
    -+  _Generic((void (*)(T, typeof(s))){},                                  \
    -           void (*)(short,              const char *):  a2sh_c,          \
    -           void (*)(short,              const void *):  a2sh_c,          \
    -           void (*)(short,              char *):        a2sh_nc,         \
    -
      ## lib/search/cmp/cmp.h ##
     @@
      
 9:  3168abcfe =  9:  8622877a0 lib/alloc/: REALLOC[F](): Move _Generic(3) to separate line
10:  869afab38 = 10:  b11b780c0 lib/, src/: Rename REALLOCF() => reallocf_T()
11:  c8bfddd41 = 11:  be0cd1060 lib/: Rename REALLOC() => realloc_T()
12:  3cb99aba0 = 12:  d9e33b125 lib/: Rename XREALLOC() => xrealloc_T()
13:  217eba94b = 13:  f2a96d60b lib/: Rename MALLOC() => malloc_T()
14:  e8acd6c67 = 14:  1fc1ebc87 lib/: Rename XMALLOC() => xmalloc_T()
15:  3e6a0b004 = 15:  2d28653a9 lib/: Rename CALLOC() => calloc_T()
16:  1543c7668 = 16:  8de9d4e4a lib/: Rename XCALLOC() => xcalloc_T()
17:  1ea155970 = 17:  2b2ad57fb lib/search/: lsearch_T(): Don't return anything
v8c
  • Rebase
$ git rd 
 1:  b4044b01d =  1:  5413a2a7e lib/: Use a consistent name for macro arguments representing a type name
 2:  1725bb81e =  2:  5de573ad6 lib/search/, lib/, src/: Add a type parameter to the type-safe macros
 3:  0ae8aac83 =  3:  fe626d787 lib/search/: Simplify CMP()
 4:  0bb83a0bc =  4:  948fb0bb7 lib/search/: Split APIs
 5:  c8b88d8f3 =  5:  ff3ca8afa lib/sizeof.h: typeas(): Add macro
 6:  8557266d3 =  6:  8e3450183 lib/{alloc,search}/: Use typeas() to add support for arbitrary types
 7:  666f7a4e9 =  7:  0a2f0141a lib/alloc/: reallocarray[f]_(): Add helper macros to handle n?:1
 8:  435059189 =  8:  3ba496f29 lib/: Use compound literals to avoid casts
 9:  8622877a0 =  9:  a9965f0fd lib/alloc/: REALLOC[F](): Move _Generic(3) to separate line
10:  b11b780c0 = 10:  3e677f1ef lib/, src/: Rename REALLOCF() => reallocf_T()
11:  be0cd1060 ! 11:  fae5f4387 lib/: Rename REALLOC() => realloc_T()
    @@ lib/shadow/gshadow/fgetsgent.c: fgetsgent(FILE *fp)
                }
     
      ## lib/subordinateio.c ##
    -@@ lib/subordinateio.c: static bool append_range(struct subid_range **ranges, const struct subordinate_r
    +@@ lib/subordinateio.c: static bool have_range(struct commonio_db *db,
    + static struct subid_range *
    + append_range(struct subid_range *ranges, const struct subordinate_range *new, int n)
      {
    -   struct subid_range  *sr;
    - 
    --  sr = REALLOC(*ranges, n + 1, struct subid_range);
    -+  sr = realloc_T(*ranges, n + 1, struct subid_range);
    -   if (!sr)
    -           return false;
    +-  ranges = REALLOCF(ranges, n + 1, struct subid_range);
    ++  ranges = reallocf_T(ranges, n + 1, struct subid_range);
    +   if (ranges == NULL)
    +           return NULL;
      
12:  d9e33b125 = 12:  b83b47dbd lib/: Rename XREALLOC() => xrealloc_T()
13:  f2a96d60b ! 13:  26c5efbff lib/: Rename MALLOC() => malloc_T()
    @@ tests/libsubid/04_nss/libsubid_zzz.c: enum subid_status shadow_subid_list_owner_
        if (strcmp(owner, "user1") == 0 || strcmp(owner, "group1") == 0) {
     
      ## tests/unit/test_chkname.c ##
    -@@ tests/unit/test_chkname.c: test_is_valid_user_name_long(void **state)
    +@@ tests/unit/test_chkname.c: test_is_valid_user_name_long(void **)
        char    *name;
      
        max = sysconf(_SC_LOGIN_NAME_MAX);
14:  1fc1ebc87 ! 14:  857c8cbfd lib/: Rename XMALLOC() => xmalloc_T()
    @@ src/usermod.c: int main (int argc, char **argv)
        is_shadow_pwd = spw_file_present ();
     
      ## tests/unit/test_exit_if_null.c ##
    -@@ tests/unit/test_exit_if_null.c: test_exit_if_null_exit(void **state)
    +@@ tests/unit/test_exit_if_null.c: test_exit_if_null_exit(void **)
        switch (setjmp(jmpb)) {
        case 0:
                p = "called";
    @@ tests/unit/test_exit_if_null.c: test_exit_if_null_exit(void **state)
                assert_unreachable();
                break;
        case EXIT_CALLED:
    -@@ tests/unit/test_exit_if_null.c: test_exit_if_null_ok(void **state)
    +@@ tests/unit/test_exit_if_null.c: test_exit_if_null_ok(void **)
      
        static const char  foo[] = "foo1bar";
      
15:  2d28653a9 = 15:  bb54d6415 lib/: Rename CALLOC() => calloc_T()
16:  8de9d4e4a = 16:  ed208f3c5 lib/: Rename XCALLOC() => xcalloc_T()
17:  2b2ad57fb = 17:  01221f1d9 lib/search/: lsearch_T(): Don't return anything
v9
$ git range-diff typeas gh/T T
 1:  5de573ad6 <  -:  --------- lib/search/, lib/, src/: Add a type parameter to the type-safe macros
 2:  fe626d787 <  -:  --------- lib/search/: Simplify CMP()
 3:  948fb0bb7 <  -:  --------- lib/search/: Split APIs
 4:  ff3ca8afa <  -:  --------- lib/sizeof.h: typeas(): Add macro
 5:  8e3450183 <  -:  --------- lib/{alloc,search}/: Use typeas() to add support for arbitrary types
 6:  0a2f0141a =  1:  b9ef0f848 lib/alloc/: reallocarray[f]_(): Add helper macros to handle n?:1
 7:  3ba496f29 =  2:  a123305a2 lib/: Use compound literals to avoid casts
 8:  a9965f0fd =  3:  132ea19cc lib/alloc/: REALLOC[F](): Move _Generic(3) to separate line
 9:  3e677f1ef =  4:  a8f9913bf lib/, src/: Rename REALLOCF() => reallocf_T()
10:  fae5f4387 =  5:  21a5df90e lib/: Rename REALLOC() => realloc_T()
11:  b83b47dbd =  6:  7de00ca19 lib/: Rename XREALLOC() => xrealloc_T()
12:  26c5efbff =  7:  921fb8396 lib/: Rename MALLOC() => malloc_T()
13:  857c8cbfd =  8:  c9a6237f5 lib/: Rename XMALLOC() => xmalloc_T()
14:  bb54d6415 =  9:  35ece6ea7 lib/: Rename CALLOC() => calloc_T()
15:  ed208f3c5 = 10:  d2f190d6f lib/: Rename XCALLOC() => xcalloc_T()
16:  01221f1d9 = 11:  a82104e3a lib/search/: lsearch_T(): Don't return anything
v9b
  • Rebase
$ git range-diff gh/typeas..gh/T typeas..T 
 1:  b9ef0f848 =  1:  52135f7c9 lib/alloc/: reallocarray[f]_(): Add helper macros to handle n?:1
 2:  a123305a2 =  2:  1490e1742 lib/: Use compound literals to avoid casts
 3:  132ea19cc =  3:  dc4ec0d3f lib/alloc/: REALLOC[F](): Move _Generic(3) to separate line
 4:  a8f9913bf =  4:  ddf54ff42 lib/, src/: Rename REALLOCF() => reallocf_T()
 5:  21a5df90e =  5:  74d01b5e6 lib/: Rename REALLOC() => realloc_T()
 6:  7de00ca19 =  6:  a1275b131 lib/: Rename XREALLOC() => xrealloc_T()
 7:  921fb8396 =  7:  7d451cc04 lib/: Rename MALLOC() => malloc_T()
 8:  c9a6237f5 =  8:  97ab0f08b lib/: Rename XMALLOC() => xmalloc_T()
 9:  35ece6ea7 =  9:  7720e8e2c lib/: Rename CALLOC() => calloc_T()
10:  d2f190d6f = 10:  1e684e55a lib/: Rename XCALLOC() => xcalloc_T()
11:  a82104e3a = 11:  529d0c2af lib/search/: lsearch_T(): Don't return anything
v10
  • Rebase
$ git rd 
 1:  4f95f69bc <  -:  --------- lib/: Use a consistent name for macro arguments representing a type name
 2:  a10273be8 <  -:  --------- lib/search/, lib/, src/: Add a type parameter to the type-safe macros
 3:  01e68361b <  -:  --------- lib/search/: Simplify CMP()
 4:  822f7da29 <  -:  --------- lib/search/: Split APIs
 5:  34c1f823a <  -:  --------- lib/sizeof.h: typeas(): Add macro
 6:  9dd442b84 <  -:  --------- lib/{alloc,search}/: Use typeas() to add support for arbitrary types
 7:  52135f7c9 =  1:  71527d880 lib/alloc/: reallocarray[f]_(): Add helper macros to handle n?:1
 8:  1490e1742 =  2:  d52d51e36 lib/: Use compound literals to avoid casts
 9:  dc4ec0d3f =  3:  1504633e5 lib/alloc/: REALLOC[F](): Move _Generic(3) to separate line
10:  ddf54ff42 =  4:  ff4d84940 lib/, src/: Rename REALLOCF() => reallocf_T()
11:  74d01b5e6 =  5:  f067daa7d lib/: Rename REALLOC() => realloc_T()
12:  a1275b131 =  6:  238a917ed lib/: Rename XREALLOC() => xrealloc_T()
13:  7d451cc04 =  7:  81450b755 lib/: Rename MALLOC() => malloc_T()
14:  97ab0f08b !  8:  27327364c lib/: Rename XMALLOC() => xmalloc_T()
    @@ lib/utmp.c: get_current_utmp(pid_t main_pid)
        }
     
      ## src/gpasswd.c ##
    -@@ src/gpasswd.c: static void get_group (struct group *gr, struct option_flags *flags)
    +@@ src/gpasswd.c: static void get_group(struct group *gr, const struct option_flags *flags)
      
                        sg->sg_mem = dup_list (gr->gr_mem);
      
15:  7720e8e2c =  9:  83299ca80 lib/: Rename CALLOC() => calloc_T()
16:  1e684e55a = 10:  4cd4a3785 lib/: Rename XCALLOC() => xcalloc_T()
17:  529d0c2af = 11:  eb1e8838b lib/search/: lsearch_T(): Don't return anything
v10b
  • Rebase
$ git rd 
 1:  71527d880 =  1:  a598da374 lib/alloc/: reallocarray[f]_(): Add helper macros to handle n?:1
 2:  d52d51e36 !  2:  a3588a156 lib/: Use compound literals to avoid casts
    @@ lib/search/cmp/cmp.h
      ## lib/search/l/lfind.h ##
     @@
      ({                                                                    \
    -   _Generic(k, T *: 0, const T *: 0);                            \
    -   _Generic(a, T *: 0, const T *: 0);                            \
    +   _Generic(k, T *: (void)0, const T *: (void)0);                \
    +   _Generic(a, T *: (void)0, const T *: (void)0);                \
     -  (T *) lfind_(k, a, n, sizeof(T), cmp);                        \
     +  (T *){lfind_(k, a, n, sizeof(T), cmp)};                       \
      })
    @@ lib/search/l/lfind.h
      ## lib/search/l/lsearch.h ##
     @@
      ({                                                                    \
    -   _Generic(k, T *: 0, const T *: 0);                            \
    -   _Generic(a, T *: 0);                                          \
    +   _Generic(k, T *: (void)0, const T *: (void)0);                \
    +   _Generic(a, T *: (void)0);                                    \
     -  (T *) lsearch(k, a, n, sizeof(T), cmp);                       \
     +  (T *){lsearch(k, a, n, sizeof(T), cmp)};                      \
      })
 3:  1504633e5 =  3:  67b6e9b6b lib/alloc/: REALLOC[F](): Move _Generic(3) to separate line
 4:  ff4d84940 =  4:  a8450c1c3 lib/, src/: Rename REALLOCF() => reallocf_T()
 5:  f067daa7d =  5:  5cebc506e lib/: Rename REALLOC() => realloc_T()
 6:  238a917ed =  6:  44f986969 lib/: Rename XREALLOC() => xrealloc_T()
 7:  81450b755 =  7:  3e9cb041c lib/: Rename MALLOC() => malloc_T()
 8:  27327364c =  8:  04009b923 lib/: Rename XMALLOC() => xmalloc_T()
 9:  83299ca80 =  9:  f7ceebc49 lib/: Rename CALLOC() => calloc_T()
10:  4cd4a3785 = 10:  87d3f68f7 lib/: Rename XCALLOC() => xcalloc_T()
11:  eb1e8838b ! 11:  24b641c89 lib/search/: lsearch_T(): Don't return anything
    @@ lib/search/l/lsearch.h
     -({                                                                    \
     +#define lsearch_T_(T, k, a, n, cmp)  do                               \
     +{                                                                     \
    -   _Generic(k, T *: 0, const T *: 0);                            \
    -   _Generic(a, T *: 0);                                          \
    +   _Generic(k, T *: (void)0, const T *: (void)0);                \
    +   _Generic(a, T *: (void)0);                                    \
     -  (T *){lsearch(k, a, n, sizeof(T), cmp)};                      \
     -})
     +  lsearch(k, a, n, sizeof(T), cmp);                             \
v11
  • Use (void)0 to avoid -Wunused-value diagnostics.
$ git rd 
 1:  a598da374 =  1:  a598da374 lib/alloc/: reallocarray[f]_(): Add helper macros to handle n?:1
 2:  a3588a156 =  2:  a3588a156 lib/: Use compound literals to avoid casts
 3:  67b6e9b6b !  3:  d2ba4e01b lib/alloc/: REALLOC[F](): Move _Generic(3) to separate line
    @@ lib/alloc/realloc.h
      #define REALLOC_(p, n, T)                                             \
      ({                                                                    \
     -  _Generic(p, T *: (T *){reallocarray_(p, n, sizeof(T))});      \
    -+  _Generic(p, T *: 0);                                          \
    ++  _Generic(p, T *: (void)0);                                    \
     +  (T *){reallocarray_(p, n, sizeof(T))};                        \
      })
      
    @@ lib/alloc/reallocf.h
      #define REALLOCF_(p, n, T)                                            \
      ({                                                                    \
     -  _Generic(p, T *: (T *){reallocarrayf_(p, n, sizeof(T))});     \
    -+  _Generic(p, T *: 0);                                          \
    ++  _Generic(p, T *: (void)0);                                    \
     +  (T *){reallocarrayf_(p, n, sizeof(T))};                       \
      })
      
 4:  a8450c1c3 !  4:  1972f8a7b lib/, src/: Rename REALLOCF() => reallocf_T()
    @@ lib/alloc/reallocf.h
     +#define reallocf_T(p, n, T)   reallocf_T_(p, n, typeas(T))
     +#define reallocf_T_(p, n, T)                                          \
      ({                                                                    \
    -   _Generic(p, T *: 0);                                          \
    +   _Generic(p, T *: (void)0);                                    \
        (T *){reallocarrayf_(p, n, sizeof(T))};                       \
     @@
      #define reallocarrayf_(p, n, size)  reallocarrayf(p, (n) ?: 1, (size) ?: 1)
 5:  5cebc506e !  5:  f00cb135f lib/: Rename REALLOC() => realloc_T()
    @@ lib/alloc/realloc.h
     +#define realloc_T(p, n, T)   realloc_T_(p, n, typeas(T))
     +#define realloc_T_(p, n, T)                                           \
      ({                                                                    \
    -   _Generic(p, T *: 0);                                          \
    +   _Generic(p, T *: (void)0);                                    \
        (T *){reallocarray_(p, n, sizeof(T))};                        \
     @@
      #define reallocarray_(p, n, size)  reallocarray(p, (n) ?: 1, (size) ?: 1)
 6:  44f986969 =  6:  6b2a79d41 lib/: Rename XREALLOC() => xrealloc_T()
 7:  3e9cb041c =  7:  b07be81b7 lib/: Rename MALLOC() => malloc_T()
 8:  04009b923 =  8:  1bbdf9e8a lib/: Rename XMALLOC() => xmalloc_T()
 9:  f7ceebc49 =  9:  f6668c68b lib/: Rename CALLOC() => calloc_T()
10:  87d3f68f7 = 10:  93068ca20 lib/: Rename XCALLOC() => xcalloc_T()
11:  24b641c89 = 11:  ed5996d1b lib/search/: lsearch_T(): Don't return anything
v11b
  • Rebase
$ git rd 
 1:  a598da374 =  1:  a190eb942 lib/alloc/: reallocarray[f]_(): Add helper macros to handle n?:1
 2:  a3588a156 =  2:  52a19082b lib/: Use compound literals to avoid casts
 3:  d2ba4e01b =  3:  a215b3b89 lib/alloc/: REALLOC[F](): Move _Generic(3) to separate line
 4:  1972f8a7b !  4:  e478a811f lib/, src/: Rename REALLOCF() => reallocf_T()
    @@ lib/alloc/reallocf.h
      ATTR_MALLOC(free)
      inline void *reallocarrayf(void *p, size_t nmemb, size_t size);
     
    - ## lib/commonio.c ##
    -@@ lib/commonio.c: int commonio_open (struct commonio_db *db, int mode)
    -                   size_t len;
    - 
    -                   buflen += BUFLEN;
    --                  buf = REALLOCF(buf, buflen, char);
    -+                  buf = reallocf_T(buf, buflen, char);
    -                   if (NULL == buf)
    -                           goto cleanup_errno;
    - 
    -
      ## lib/subordinateio.c ##
     @@ lib/subordinateio.c: static int append_uids(uid_t **uids, const char *owner, int n)
                        return n;
 5:  f00cb135f !  5:  e756b580a lib/: Rename REALLOC() => realloc_T()
    @@ lib/alloc/realloc.h
      
      #endif  // include guard
     
    - ## lib/shadow/gshadow/fgetsgent.c ##
    -@@ lib/shadow/gshadow/fgetsgent.c: fgetsgent(FILE *fp)
    -          && (feof (fp) == 0)) {
    -           size_t len;
    - 
    --          cp = REALLOC(buf, buflen * 2, char);
    -+          cp = realloc_T(buf, buflen * 2, char);
    -           if (NULL == cp) {
    -                   return NULL;
    -           }
    -
      ## lib/subordinateio.c ##
     @@ lib/subordinateio.c: static bool have_range(struct commonio_db *db,
      static struct subid_range *
 6:  6b2a79d41 =  6:  6d5a77730 lib/: Rename XREALLOC() => xrealloc_T()
 7:  b07be81b7 !  7:  966291ac4 lib/: Rename MALLOC() => malloc_T()
    @@ lib/alloc/malloc.h
      inline void *mallocarray(size_t nmemb, size_t size);
     
      ## lib/commonio.c ##
    -@@ lib/commonio.c: int commonio_open (struct commonio_db *db, int mode)
    -   }
    - 
    -   buflen = BUFLEN;
    --  buf = MALLOC(buflen, char);
    -+  buf = malloc_T(buflen, char);
    -   if (NULL == buf)
    -           goto cleanup_errno;
    - 
    -@@ lib/commonio.c: int commonio_open (struct commonio_db *db, int mode)
    +@@ lib/commonio.c: commonio_open(struct commonio_db *db, int mode)
                        }
                }
      
    @@ lib/shadow/grp/agetgroups.h: agetgroups(size_t *ngids)
                return NULL;
      
     
    - ## lib/shadow/gshadow/fgetsgent.c ##
    -@@ lib/shadow/gshadow/fgetsgent.c: fgetsgent(FILE *fp)
    -   char *cp;
    - 
    -   if (0 == buflen) {
    --          buf = MALLOC(BUFSIZ, char);
    -+          buf = malloc_T(BUFSIZ, char);
    -           if (NULL == buf) {
    -                   return NULL;
    -           }
    -
      ## lib/shadow/gshadow/putsgent.c ##
     @@ lib/shadow/gshadow/putsgent.c: putsgent(const struct sgrp *sgrp, FILE *fp)
                size += strlen (sgrp->sg_mem[i]) + 1;
 8:  1bbdf9e8a =  8:  2ae0eda4e lib/: Rename XMALLOC() => xmalloc_T()
 9:  f6668c68b =  9:  bf94bb229 lib/: Rename CALLOC() => calloc_T()
10:  93068ca20 = 10:  22f581bf6 lib/: Rename XCALLOC() => xcalloc_T()
11:  ed5996d1b = 11:  d3eaf4ccc lib/search/: lsearch_T(): Don't return anything

@alejandro-colomar alejandro-colomar changed the title Some improvements to type-safe wrapper macros Some improvements to type-safe macros Nov 15, 2025
@alejandro-colomar alejandro-colomar marked this pull request as ready for review November 15, 2025 22:40
@alejandro-colomar alejandro-colomar marked this pull request as draft December 4, 2025 17:37
@alejandro-colomar alejandro-colomar marked this pull request as ready for review December 5, 2025 14:55
Casts are unsafe.

Compound literals also have the ability of converting values, but they
don't have the unwanted effects on safety --casts disable most useful
diagnostics--.

Compound literals are lvalues, which means their address can be taken,
and they can also be assigned to.  To avoid this, we force lvalue
conversion through a statement expression.

Signed-off-by: Alejandro Colomar <[email protected]>
This should be more readable.

Signed-off-by: Alejandro Colomar <[email protected]>
The 'T' in the name notes that this API is a type-safe variant of the
API it wraps.  This makes the names more explicative.

Signed-off-by: Alejandro Colomar <[email protected]>
The 'T' in the name notes that this API is a type-safe variant of the
API it wraps.  This makes the names more explicative.

Signed-off-by: Alejandro Colomar <[email protected]>
The 'T' in the name notes that this API is a type-safe variant of the
API it wraps.  This makes the names more explicative.

Signed-off-by: Alejandro Colomar <[email protected]>
The 'T' in the name notes that this API is a type-safe variant of the
API it wraps.  This makes the names more explicative.

Signed-off-by: Alejandro Colomar <[email protected]>
The 'T' in the name notes that this API is a type-safe variant of the
API it wraps.  This makes the names more explicative.

Signed-off-by: Alejandro Colomar <[email protected]>
The 'T' in the name notes that this API is a type-safe variant of the
API it wraps.  This makes the names more explicative.

Signed-off-by: Alejandro Colomar <[email protected]>
The 'T' in the name notes that this API is a type-safe variant of the
API it wraps.  This makes the names more explicative.

Signed-off-by: Alejandro Colomar <[email protected]>
We don't use this value.  This silences a diagnostic about the unused
return value.

Signed-off-by: Alejandro Colomar <[email protected]>
@hallyn hallyn merged commit e7771cc into shadow-maint:master Dec 6, 2025
11 checks passed
@alejandro-colomar alejandro-colomar self-assigned this Dec 27, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants