[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: alignof failure
From: |
Simon Josefsson |
Subject: |
Re: alignof failure |
Date: |
Fri, 29 May 2009 11:01:53 +0200 |
User-agent: |
Gnus/5.110011 (No Gnus v0.11) Emacs/23.0.94 (gnu/linux) |
Simon Josefsson <address@hidden> writes:
> Bruno Haible <address@hidden> writes:
>
>> Simon Josefsson wrote:
>>> The alignof module seems to have problems:
>>>
>>> address@hidden:~/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 ()
{