All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alejandro Colomar <alx.manpages@gmail.com>
To: linux-man <linux-man@vger.kernel.org>
Cc: Andrew Clayton <andrew@digital-domain.net>
Subject: Re: _Generic.3: EXAMPLES: C++'s static_cast() in C
Date: Fri, 11 Nov 2022 22:40:39 +0100	[thread overview]
Message-ID: <c583b742-9582-ceaa-aaf7-097cecb78a2e@gmail.com> (raw)
In-Reply-To: <71b02e3a-d710-cda0-6ae6-5f12c664b7f8@gmail.com>


[-- Attachment #1.1: Type: text/plain, Size: 7080 bytes --]

On 11/11/22 18:08, Alejandro Colomar wrote:>>>> Dear readers,
>>>>
>>>> I've been developing a cast macro for C that is similar to C++'s 
>>>> static_cast(), which allows to:
>>>>
>>>> - Cast between a limited set of types (actually, pointers to those types).
>>>> - Can add const, but not remove it.
>>>> - Easily grep for all casts.
>>>>
>>>> But forbids:
>>>>
>>>> - Cast between unrelated types.
>>>> - Removing const.
>>>>
>>>> This improves type safety in C, where casts allow programmers to commit all 
>>>> kinds of crimes by disabling most compiler warnings.
>>>>
>>>> The macro I originally wrote, allows to convert between u_char and char, for 
>>>> a code base that uses u_char internally but has to interface libc and 
>>>> syscalls. That one is unnecessary for most code bases which just use char 
>>>> (and that's how it should be for strings; if you want unsigned 'char's, you 
>>>> should use '-funsigned-char').
>>>>
>>>> But there are cases where the kernel or libc forces us to use casts, like 
>>>> for example in bind(2).  That's for what the following macro is, and I plan 
>>>> to add it to the EXAMPLES section in _Generic(3), replacing the previous 
>>>> program.
>>>>
>>>> The macro itself is quite huge, which might discourage some, but it is not 
>>>> so complex.  I'll release it to the public domain.  Could you please review it?
>>>>
>>>> Cheers,
>>>>
>>>> Alex
>>>>
>>>
>>> With C2x's typeof_unqual(), it can be made a bit smaller, and better (it now 
>>> supports volatile).
>>
>>
>> And since it makes no sense to convert between some of the derivative types 
>> (e.g., sa_in to sa_un), it can be further simplified:
>>
> v4:
> 
> - Reintroduce some typeof_unqual() that were accidentally removed in v3.
> - Align casts for readability.
> 

v5:

- Casting to sockaddr_storage is useless.  Only casting from it makes sense.

I'll send shortly after an v6, if I manage to simplify after this change, but 
I'll post this v5 to not have a sudden jump with an unreadably interdiff.

#define sockaddr_cast(t, p)                            \
     _Generic(&*(p),                                    \
     struct sockaddr *:                                 \
         _Generic((typeof_unqual(t)) NULL,              \
         struct sockaddr_in *:             (t) (p),     \
         struct sockaddr_in6 *:            (t) (p),     \
         struct sockaddr_un *:             (t) (p),     \
         default: (p)),                                 \
     struct sockaddr **:                                \
         _Generic((typeof_unqual(t)) NULL,              \
         struct sockaddr_in **:            (t) (p),     \
         struct sockaddr_in6 **:           (t) (p),     \
         struct sockaddr_un **:            (t) (p),     \
         default: (p)),                                 \
     const struct sockaddr *:                           \
         _Generic((t) NULL,                             \
         const struct sockaddr_in *:       (t) (p),     \
         const struct sockaddr_in6 *:      (t) (p),     \
         const struct sockaddr_un *:       (t) (p),     \
         default: (p)),                                 \
                                                        \
     struct sockaddr_in *:                              \
         _Generic((typeof_unqual(t)) NULL,              \
         struct sockaddr *:                (t) (p),     \
         default: (p)),                                 \
     struct sockaddr_in **:                             \
         _Generic((typeof_unqual(t)) NULL,              \
         struct sockaddr **:               (t) (p),     \
         default: (p)),                                 \
     const struct sockaddr_in *:                        \
         _Generic((t) NULL,                             \
         const struct sockaddr *:          (t) (p),     \
         default: (p)),                                 \
                                                        \
     struct sockaddr_in6 *:                             \
         _Generic((typeof_unqual(t)) NULL,              \
         struct sockaddr *:                (t) (p),     \
         default: (p)),                                 \
     struct sockaddr_in6 **:                            \
         _Generic((typeof_unqual(t)) NULL,              \
         struct sockaddr **:               (t) (p),     \
         default: (p)),                                 \
     const struct sockaddr_in6 *:                       \
         _Generic((t) NULL,                             \
         const struct sockaddr *:          (t) (p),     \
         default: (p)),                                 \
                                                        \
     struct sockaddr_un *:                              \
         _Generic((typeof_unqual(t)) NULL,              \
         struct sockaddr *:                (t) (p),     \
         default: (p)),                                 \
     struct sockaddr_un **:                             \
         _Generic((typeof_unqual(t)) NULL,              \
         struct sockaddr **:               (t) (p),     \
         default: (p)),                                 \
     const struct sockaddr_un *:                        \
         _Generic((t) NULL,                             \
         const struct sockaddr *:          (t) (p),     \
         default: (p)),                                 \
                                                        \
     struct sockaddr_storage *:                         \
         _Generic((typeof_unqual(t)) NULL,              \
         struct sockaddr *:                (t) (p),     \
         struct sockaddr_in *:             (t) (p),     \
         struct sockaddr_in6 *:            (t) (p),     \
         struct sockaddr_un *:             (t) (p),     \
         default: (p)),                                 \
     struct sockaddr_storage **:                        \
         _Generic((typeof_unqual(t)) NULL,              \
         struct sockaddr **:               (t) (p),     \
         struct sockaddr_in **:            (t) (p),     \
         struct sockaddr_in6 **:           (t) (p),     \
         struct sockaddr_un **:            (t) (p),     \
         default: (p)),                                 \
     const struct sockaddr_storage *:                   \
         _Generic((t) NULL,                             \
         const struct sockaddr *:          (t) (p),     \
         const struct sockaddr_in *:       (t) (p),     \
         const struct sockaddr_in6 *:      (t) (p),     \
         const struct sockaddr_un *:       (t) (p),     \
         default: (p)),                                 \
                                                        \
     default:                                           \
         (p)                                            \
     )


-- 
<http://www.alejandro-colomar.es/>

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

  reply	other threads:[~2022-11-11 21:40 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-11-11 14:53 _Generic.3: EXAMPLES: C++'s static_cast() in C Alejandro Colomar
2022-11-11 15:11 ` Alejandro Colomar
2022-11-11 16:54   ` Alejandro Colomar
2022-11-11 17:08     ` Alejandro Colomar
2022-11-11 21:40       ` Alejandro Colomar [this message]
2022-11-11 23:06         ` [PATCH v6] _Generic.3: EXAMPLES: Add sockaddr_cast() macro Alejandro Colomar
2022-11-12 14:15           ` [PATCH v7] " Alejandro Colomar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=c583b742-9582-ceaa-aaf7-097cecb78a2e@gmail.com \
    --to=alx.manpages@gmail.com \
    --cc=andrew@digital-domain.net \
    --cc=linux-man@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.