On Sun, Feb 05, 2023 at 04:28:36PM +0100, Alejandro Colomar wrote: > As discussed before, and Bastien and I seem to agree, ideally we should > define the following types: > > struct sockaddr_storage { > union { > struct { > sa_family_t ss_family; > }; > struct sockaddr_in sin; > struct sockaddr_in6 sin6; > struct sockaddr_un sun; > // ... > }; > }; AFAIK this is not permitted because of namespace. sys/socket.h is not permitted to expose sockaddr_{in,in6,un}. And if you defined differently-tagged structures with the same contents, it would not do any good; accessing the members with the wrong-tagged struct type would still be UB. Really, there is no action needed here. Nothing is wrong on libc's side. The problem is just that the type is *not useful for anything* and should not be used except in the context of sizeof, which is purely a documentation issue. > struct [[deprecated]] sockaddr { > sa_family_t sa_family; > }; > > union [[gnu::transparent_union]] sockaddr_ptr { > struct sockaddr_storage *ss; > struct sockaddr *sa; > }; > > And then we could define APIs like: > > int bind(int sockfd, const union sockaddr_ptr *addr, socklen_t len); You cannot just change APIs because you wish they were different. Ideally bind, etc. would just take void *, which is what the struct sockaddr * is being used as. But they don't, so callers have to cast. It's ugly but it's really not a big deal. Much less of a big deal than breaking the interface because you think it would look prettier if it had been done differently. Rich