Simon Josefsson <si...@josefsson.org> writes: > Bruno Haible <br...@clisp.org> writes: > >> Simon Josefsson wrote: >>> The alignof module seems to have problems: >>> >>> j...@mocca:~/src/gnulib master$ gnulib-tool --test --with-tests alignof >>> ... >>> ../../gltests/test-alignof.c:41: error: negative width in bit-field >>> ‘verify_error_if_negative_size__’ >> >> I reproduce with all versions of gcc since 3.1, on x86, when -malign-double >> is not specified. >> >> offsetof (struct { char slot1; double slot2; }, slot2) >> is 4 by default, but 8 when -malign-double is specified. >> >> Whereas >> __alignof__ (double) >> is always 8 on x86; this is even part of the GCC test suite [1]. >> >> [2] says: "It turns out that the alignment of a type can differ from the >> alignment of a field of that type. In particular, on x86 alignof(double) >> is 8, but a double as a field has alignment 4." >> >> I'm not sure which one we should use in gnulib. Probably the "alignment of a >> field of that type" semantics, because that's what we use alignof for? > > Yes. I suggest adding a comment about this, or rename alignof to > alignof_field to avoid confusion, and fix the self-test. Maybe there > could be an alignof_type macro too?
How about this patch? The test-alignof self-test still fails, so I'd like to fix this somehow. /Simon diff --git a/lib/alignof.h b/lib/alignof.h index 3752ef3..15fa56b 100644 --- a/lib/alignof.h +++ b/lib/alignof.h @@ -27,7 +27,17 @@ template <class type> struct alignof_helper { char __slot1; type __slot2; }; # define alignof(type) offsetof (alignof_helper<type>, __slot2) #else -# define alignof(type) offsetof (struct { char __slot1; type __slot2; }, __slot2) +# define alignof(type) \ + offsetof (struct { char __slot1; type __slot2; }, __slot2) +#endif + +/* Determine the alignment of a type in a struct, at compile time. */ +#if defined __cplusplus +template <class type> struct alignof_helper { char __slot1; type __slot2; }; +# define alignof_field(type) offsetof (alignof_helper<type>, __slot2) +#else +# define alignof_field(type) \ + offsetof (struct { char __slot1; type __slot2; }, __slot2) #endif #endif /* _ALIGNOF_H */ diff --git a/lib/sys_socket.in.h b/lib/sys_socket.in.h index 4553f60..5f71f34 100644 --- a/lib/sys_socket.in.h +++ b/lib/sys_socket.in.h @@ -53,11 +53,11 @@ typedef unsigned short sa_family_t; 2009-05-08, licensed under LGPLv2.1+, plus portability fixes. */ # define __ss_aligntype unsigned long int # define _SS_SIZE 256 -# define _SS_PADSIZE \ - (_SS_SIZE - ((sizeof (sa_family_t) >= alignof (__ss_aligntype) \ - ? sizeof (sa_family_t) \ - : alignof (__ss_aligntype)) \ - + sizeof (__ss_aligntype))) +# define _SS_PADSIZE \ + (_SS_SIZE - ((sizeof (sa_family_t) >= alignof_field (__ss_aligntype) \ + ? sizeof (sa_family_t) \ + : alignof_field (__ss_aligntype)) \ + + sizeof (__ss_aligntype))) struct sockaddr_storage { diff --git a/tests/test-alignof.c b/tests/test-alignof.c index 851cbf0..789b9c1 100644 --- a/tests/test-alignof.c +++ b/tests/test-alignof.c @@ -38,12 +38,29 @@ CHECK (short) CHECK (int) CHECK (long) CHECK (float) -CHECK (double) +/* The alignment of double can be different from the alignment of double + in a struct, so we can't use this test. + CHECK (double) */ CHECK (struct1) CHECK (struct2) CHECK (struct3) CHECK (struct4) +#define CHECKFIELD(type) \ + typedef struct { char slot1; type slot2; } type##_helper2; \ + verify (alignof_field (type) == offsetof (type##_helper2, slot2)); + +CHECKFIELD (char) +CHECKFIELD (short) +CHECKFIELD (int) +CHECKFIELD (long) +CHECKFIELD (float) +CHECKFIELD (double) +CHECKFIELD (struct1) +CHECKFIELD (struct2) +CHECKFIELD (struct3) +CHECKFIELD (struct4) + int main () {