[CC += Kees, Andrew] [start of thread: ] On 5/11/23 18:07, Alejandro Colomar wrote: > Hi! > > Currently, one can have pseudo-flexible array members in unions with > [0] syntax, but it's not allowed with [] syntax. > > Here's an example of how it is possible today: > > struct s { > ... > > size_t n; > union { > ptrdiff_t off[0]; // [n]; offsets from s->data. > char data[0]; > }; > }; > > which is useful to have a structure with two (or really several) > consecutive flexible arrays: one of offsets, which mark the positions > of data, and another with the actual data. Below goes an example > program, which works fine with GCC, and I believe rewriting it to > not use the union would make it less clear, since I'd need to add > casts to it. > > It works thanks to [0] pseudo-flexible arrays, but it doesn't > compile with C99 flexible arrays. And of course, [0] arrays have > issues with -fstrict-flex-arrays=3. > > > $ cat flexi4.c > #include > #include > #include > #include > > struct s { > size_t n; > union { > ptrdiff_t off[0]; > char data[0]; > }; > }; > > int > main(void) > { > char *p; > struct s *s; > > s = malloc(offsetof(struct s, off) + > sizeof(ptrdiff_t) * 2 + > sizeof("foobar") + sizeof("baz")); > > s->n = 2; > p = s->data + sizeof(ptrdiff_t) * s->n; > > s->off[0] = p - s->data; > p = stpcpy(p, "foobar") + 1; > s->off[1] = p - s->data; > p = stpcpy(p, "baz") + 1; > > puts(s->data + s->off[0]); > puts(s->data + s->off[1]); > > free(s); > } > $ gcc-13 -Wall -Wextra -Werror -fanalyzer \ > -fsanitize=undefined -fsanitize=address \ > -D_FORTIFY_SOURCE=3 -fstrict-flex-arrays=2 \ > flexi4.c > $ ./a.out > foobar > baz > $ gcc-13 -Wall -Wextra -Werror -fanalyzer \ > -fsanitize=undefined -fsanitize=address \ > -D_FORTIFY_SOURCE=3 -fstrict-flex-arrays=3 \ > flexi4.c > $ ./a.out > flexi4.c:27:8: runtime error: index 0 out of bounds for type 'ptrdiff_t [*]' > flexi4.c:29:8: runtime error: index 1 out of bounds for type 'ptrdiff_t [*]' > flexi4.c:32:23: runtime error: index 0 out of bounds for type 'ptrdiff_t [*]' > foobar > flexi4.c:33:23: runtime error: index 1 out of bounds for type 'ptrdiff_t [*]' > baz > > > Would you allow flexible array members in unions? Is there any > strong reason to disallow them? > > Currently, I get: > > $ gcc-13 -Wall -Wextra -fanalyzer \ > -fsanitize=undefined -fsanitize=address \ > -D_FORTIFY_SOURCE=3 -fstrict-flex-arrays=3 \ > flexi4-true.c > flexi4-true.c:9:28: error: flexible array member in union > 9 | ptrdiff_t off[]; > | ^~~ > flexi4-true.c:10:28: error: flexible array member in union > 10 | char data[]; > | ^~~~ > > Currently, the Linux kernel has to go through some hoops due to this restriction: $ grepc -tm __DECLARE_FLEX_ARRAY * include/uapi/linux/stddef.h:42: #define __DECLARE_FLEX_ARRAY(TYPE, NAME) \ struct { \ struct { } __empty_ ## NAME; \ TYPE NAME[]; \ } tools/include/uapi/linux/stddef.h:42: #define __DECLARE_FLEX_ARRAY(TYPE, NAME) \ struct { \ struct { } __empty_ ## NAME; \ TYPE NAME[]; \ } $ grep -rnB2 __DECLARE_FLEX_ARRAY * | head include/uapi/rdma/rdma_user_rxe.h-153- __u32 reserved; include/uapi/rdma/rdma_user_rxe.h-154- union { include/uapi/rdma/rdma_user_rxe.h:155: __DECLARE_FLEX_ARRAY(__u8, inline_data); include/uapi/rdma/rdma_user_rxe.h:156: __DECLARE_FLEX_ARRAY(__u8, atomic_wr); include/uapi/rdma/rdma_user_rxe.h:157: __DECLARE_FLEX_ARRAY(struct rxe_sge, sge); -- include/uapi/scsi/scsi_netlink_fc.h-53- union { include/uapi/scsi/scsi_netlink_fc.h-54- __u32 event_data; include/uapi/scsi/scsi_netlink_fc.h:55: __DECLARE_FLEX_ARRAY(__u8, event_data_flex); -- -- GPG key fingerprint: A9348594CE31283A826FBDD8D57633D441E25BB5