shadow-maint / shadow

Upstream shadow tree
Other
290 stars 228 forks source link

lib/alloc.h: Reimplement [X]REALLOC[F]() macros with _Generic(3) #988

Closed alejandro-colomar closed 2 months ago

alejandro-colomar commented 2 months ago

Instead of GNU builtins and extensions, these macros can be implemented with C11's _Generic(3), and the result is much simpler (and safer, since it's now an error, not just a warning).

I don't remember who showed me that trick; it was some months ago, in the gcc@ or libc-alpha@ mailing lists (maybe it was @uecker). I reimplemented these macros from scratch for neomutt(1), and did it with _Generic(3), and it was much nicer than all those GNU extensions. Let's incorporate those improvements here. :-)


Revisions:

v2 v2 changes: - Update copyright ``` $ git range-diff shadow/master gh/alloc alloc 1: 18ec0d85 ! 1: 84517ec8 lib/alloc.h: Reimplement [X]REALLOC[F]() macros with _Generic(3) @@ Commit message Signed-off-by: Alejandro Colomar ## lib/alloc.h ## +@@ +-/* +- * SPDX-FileCopyrightText: 2023, Alejandro Colomar +- * +- * SPDX-License-Identifier: BSD-3-Clause +- */ ++// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar ++// SPDX-License-Identifier: BSD-3-Clause + + + #ifndef SHADOW_INCLUDE_LIB_MALLOC_H_ @@ #define XMALLOC(n, type) ((type *) xmallocarray(n, sizeof(type))) ```
v2b - Whitespace ``` $ git range-diff gh/master gh/alloc alloc 1: 84517ec8 ! 1: bff08b61 lib/alloc.h: Reimplement [X]REALLOC[F]() macros with _Generic(3) @@ lib/alloc.h - (type *) reallocarray(p_, n, sizeof(type)); \ -}) +( \ -+ _Generic(ptr, type *: (type *) reallocarray(ptr, n, sizeof(type))) \ ++ _Generic(ptr, type *: (type *) reallocarray(ptr, n, sizeof(type))) \ +) #define REALLOCF(ptr, n, type) \ @@ lib/alloc.h - (type *) reallocarrayf(p_, n, sizeof(type)); \ -}) +( \ -+ _Generic(ptr, type *: (type *) reallocarrayf(ptr, n, sizeof(type))) \ ++ _Generic(ptr, type *: (type *) reallocarrayf(ptr, n, sizeof(type))) \ +) #define XREALLOC(ptr, n, type) \ @@ lib/alloc.h - (type *) xreallocarray(p_, n, sizeof(type)); \ -}) +( \ -+ _Generic(ptr, type *: (type *) xreallocarray(ptr, n, sizeof(type))) \ ++ _Generic(ptr, type *: (type *) xreallocarray(ptr, n, sizeof(type))) \ +) ```
v2c - Rebase ``` $ git range-diff gh/master..gh/alloc master..alloc 1: bff08b61 = 1: 51a03214 lib/alloc.h: Reimplement [X]REALLOC[F]() macros with _Generic(3) ```
alejandro-colomar commented 2 months ago

The trick is that _Generic(ptr, type *: expr) guarantees that typeof(ptr) is exactly type * (or it wouldn't compile at all), since there's no default: or alternate type in that generic expression.

alejandro-colomar commented 2 months ago

Thanks! I've come up with some similar ideas to simplify and improve other magic macros. I'll send another patch set soon. :-)